mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-03-02 03:39:21 +00:00
Refactor background resources loader - game should now load much faster and also reports progress while downloading resources
This commit is contained in:
@@ -1,115 +0,0 @@
|
||||
/**
|
||||
* ES6 Bundle Loader
|
||||
*
|
||||
* Attempts to load the game code, and if that fails tries with the transpiled
|
||||
* version. Also handles errors during load.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
var loadTimeout = null;
|
||||
var callbackDone = false;
|
||||
|
||||
// Catch load errors
|
||||
|
||||
function errorHandler(event, source, lineno, colno, error) {
|
||||
console.error("👀 Init Error:", event, source, lineno, colno, error);
|
||||
var element = document.createElement("div");
|
||||
element.style.position = "fixed";
|
||||
element.style.top = "0";
|
||||
element.style.right = "0";
|
||||
element.style.bottom = "0";
|
||||
element.style.left = "0";
|
||||
element.style.zIndex = "29999";
|
||||
element.style.backgroundColor = "#222429";
|
||||
element.style.display = "flex";
|
||||
element.style.justifyContent = "center";
|
||||
element.style.alignItems = "center";
|
||||
|
||||
var inner = document.createElement("div");
|
||||
inner.style.color = "#fff";
|
||||
inner.style.fontFamily = "GameFont, sans-serif";
|
||||
inner.style.fontSize = "15px";
|
||||
inner.style.padding = "30px";
|
||||
inner.style.textAlign = "center";
|
||||
element.appendChild(inner);
|
||||
|
||||
var heading = document.createElement("h3");
|
||||
heading.style.color = "#ef5072";
|
||||
heading.innerText = "Error";
|
||||
heading.style.marginBottom = "40px";
|
||||
heading.style.fontSize = "45px";
|
||||
inner.appendChild(heading);
|
||||
|
||||
var content = document.createElement("p");
|
||||
content.style.color = "#eee";
|
||||
content.innerText = error || (event && event.message) || event || "Unknown Error";
|
||||
inner.appendChild(content);
|
||||
|
||||
if (source) {
|
||||
var sourceElement = document.createElement("p");
|
||||
sourceElement.style.color = "#777";
|
||||
sourceElement.innerText = sourceElement + ":" + lineno + ":" + colno;
|
||||
inner.appendChild(sourceElement);
|
||||
}
|
||||
|
||||
document.documentElement.appendChild(element);
|
||||
}
|
||||
|
||||
if (window.location.host.indexOf("localhost") < 0) {
|
||||
window.addEventListener("error", errorHandler);
|
||||
window.addEventListener("unhandledrejection", errorHandler);
|
||||
}
|
||||
|
||||
function makeJsTag(src, integrity) {
|
||||
var script = document.createElement("script");
|
||||
script.src = src;
|
||||
script.type = "text/javascript";
|
||||
script.charset = "utf-8";
|
||||
script.defer = true;
|
||||
if (integrity) {
|
||||
script.setAttribute("integrity", integrity);
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
// function loadFallbackJs(error) {
|
||||
// console.warn("👀 ES6 Script not supported, loading transpiled code.");
|
||||
// console.warn("👀 Error was:", error);
|
||||
// var scriptTransp = makeJsTag(bundleSrcTranspiled, bundleIntegrityTranspiled);
|
||||
// scriptTransp.addEventListener("error", scriptFail);
|
||||
// scriptTransp.addEventListener("load", onJsLoaded);
|
||||
// document.head.appendChild(scriptTransp);
|
||||
// }
|
||||
|
||||
function scriptFail(error) {
|
||||
console.error("👀 Failed to load bundle!");
|
||||
console.error("👀 Error was:", error);
|
||||
throw new Error("Core load failed.");
|
||||
}
|
||||
|
||||
function expectJsParsed() {
|
||||
if (!callbackDone) {
|
||||
console.error("👀 Got no core callback");
|
||||
throw new Error("Core thread failed to respond within time.");
|
||||
}
|
||||
}
|
||||
|
||||
function onJsLoaded() {
|
||||
console.log("👀 Core loaded at", Math.floor(performance.now()), "ms");
|
||||
loadTimeout = setTimeout(expectJsParsed, 15000);
|
||||
window.removeEventListener("error", errorHandler);
|
||||
window.removeEventListener("unhandledrejection", errorHandler);
|
||||
}
|
||||
|
||||
window.coreThreadLoadedCb = function () {
|
||||
console.log("👀 Core responded at", Math.floor(performance.now()), "ms");
|
||||
clearTimeout(loadTimeout);
|
||||
loadTimeout = null;
|
||||
callbackDone = true;
|
||||
};
|
||||
|
||||
var scriptEs6 = makeJsTag(bundleSrc, bundleIntegrity);
|
||||
// scriptEs6.addEventListener("error", loadFallbackJs);
|
||||
scriptEs6.addEventListener("load", onJsLoaded);
|
||||
document.head.appendChild(scriptEs6);
|
||||
})();
|
||||
@@ -165,7 +165,7 @@ function serveHTML({ version = "web-dev" }) {
|
||||
|
||||
// Watch .html files, those trigger a html rebuild
|
||||
gulp.watch("../src/**/*.html", gulp.series("html." + version + ".dev"));
|
||||
gulp.watch("./preloader.css", gulp.series("html." + version + ".dev"));
|
||||
gulp.watch("./preloader/*.*", gulp.series("html." + version + ".dev"));
|
||||
|
||||
// Watch translations
|
||||
gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson"));
|
||||
|
||||
34
gulp/html.js
34
gulp/html.js
File diff suppressed because one or more lines are too long
@@ -47,7 +47,7 @@ body {
|
||||
}
|
||||
|
||||
#ll_fp {
|
||||
font-family: GameFont;
|
||||
font-family: "GameFont", Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
@@ -89,8 +89,9 @@ body {
|
||||
#ll_loader > .ll_text {
|
||||
text-align: center;
|
||||
color: #777a7f;
|
||||
font-family: "GameFont", sans-serif;
|
||||
font-family: "GameFont", Arial, sans-serif;
|
||||
font-size: 24px;
|
||||
height: 30px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
@@ -98,60 +99,39 @@ body {
|
||||
width: 80vw;
|
||||
max-width: 800px;
|
||||
margin-top: 40px;
|
||||
height: 14px;
|
||||
height: 7px;
|
||||
border-radius: 20px;
|
||||
background: rgba(0, 10, 40, 0.1);
|
||||
border: 5px solid transparent;
|
||||
background: rgba(0, 10, 20, 0.08);
|
||||
|
||||
/* border: 5px solid transparent; */
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
@keyframes LL_LoadingAnimation {
|
||||
0% {
|
||||
width: 0%;
|
||||
background-color: #777a7f;
|
||||
}
|
||||
19.99% {
|
||||
width: 99.5%;
|
||||
background-color: rgb(50, 197, 121);
|
||||
}
|
||||
20% {
|
||||
width: 0%;
|
||||
background-color: #777a7f;
|
||||
}
|
||||
49.99% {
|
||||
width: 98%;
|
||||
background-color: #4fbfce;
|
||||
}
|
||||
50% {
|
||||
width: 0%;
|
||||
background-color: #777a7f;
|
||||
}
|
||||
74.99% {
|
||||
width: 98%;
|
||||
background-color: #74a8c0;
|
||||
}
|
||||
75% {
|
||||
width: 0%;
|
||||
background-color: #777a7f;
|
||||
}
|
||||
100% {
|
||||
width: 98%;
|
||||
background-color: #a186d4;
|
||||
background-color: #34ae67;
|
||||
}
|
||||
}
|
||||
|
||||
#ll_progressbar > span {
|
||||
border-radius: 20px;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 98%;
|
||||
height: 190%;
|
||||
width: 5%;
|
||||
background: #fff;
|
||||
transform: translateY(-50%);
|
||||
top: 50%;
|
||||
display: inline-flex;
|
||||
animation: LL_LoadingAnimation 90s ease-in-out infinite;
|
||||
background-color: #269fba;
|
||||
animation: LL_LoadingAnimation 4s ease-in-out infinite;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
border: 4px solid #d5d8de;
|
||||
/* box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); */
|
||||
transition: width 0.5s ease-in-out;
|
||||
min-width: 4%;
|
||||
}
|
||||
|
||||
#ll_progressbar > #ll_loadinglabel {
|
||||
@@ -181,10 +161,10 @@ body {
|
||||
#ll_standalone {
|
||||
text-align: center;
|
||||
color: #777a7f;
|
||||
margin-top: 20px;
|
||||
margin-top: 30px;
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
animation: ShowStandaloneBannerAfterDelay 30s linear;
|
||||
animation: ShowStandaloneBannerAfterDelay 60s linear;
|
||||
}
|
||||
|
||||
#ll_standalone a {
|
||||
@@ -212,13 +192,71 @@ body {
|
||||
|
||||
#ll_preload_status {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
top: 40px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 100;
|
||||
color: rgba(#000, 0.4);
|
||||
opacity: 1 !important;
|
||||
font-size: 12px;
|
||||
font-size: 18px;
|
||||
color: rgba(0, 10, 20, 0.5);
|
||||
|
||||
font-family: "GameFont", Arial, sans-serif;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#ll_preload_error {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 999999;
|
||||
background: #d5d8de;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#ll_preload_error > .inner {
|
||||
color: #fff;
|
||||
font-family: Arial, "sans-serif";
|
||||
font-size: 15px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#ll_preload_error > .inner > .heading {
|
||||
color: #ef5072;
|
||||
margin-bottom: 40px;
|
||||
font-size: 45px;
|
||||
}
|
||||
|
||||
#ll_preload_error > .inner > .content {
|
||||
color: #55585f;
|
||||
font-family: monospace;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#ll_preload_error > .inner .discordLink {
|
||||
color: #333;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
font-family: Arial;
|
||||
}
|
||||
|
||||
#ll_preload_error > .inner .discordLink a {
|
||||
color: #39f;
|
||||
}
|
||||
#ll_preload_error > .inner .discordLink strong {
|
||||
font-weight: 900 !important;
|
||||
}
|
||||
|
||||
#ll_preload_error > .inner .source {
|
||||
color: #777;
|
||||
}
|
||||
21
gulp/preloader/preloader.html
Normal file
21
gulp/preloader/preloader.html
Normal file
File diff suppressed because one or more lines are too long
127
gulp/preloader/preloader.js
Normal file
127
gulp/preloader/preloader.js
Normal file
@@ -0,0 +1,127 @@
|
||||
(function () {
|
||||
var loadTimeout = null;
|
||||
var callbackDone = false;
|
||||
|
||||
// Catch load errors
|
||||
|
||||
function errorHandler(event, source, lineno, colno, error) {
|
||||
console.error("👀 Init Error:", event, source, lineno, colno, error);
|
||||
var element = document.createElement("div");
|
||||
element.id = "ll_preload_error";
|
||||
|
||||
var inner = document.createElement("div");
|
||||
inner.classList.add("inner");
|
||||
element.appendChild(inner);
|
||||
|
||||
var heading = document.createElement("h3");
|
||||
heading.classList.add("heading");
|
||||
heading.innerText = "Fatal Error";
|
||||
inner.appendChild(heading);
|
||||
|
||||
var content = document.createElement("p");
|
||||
content.classList.add("content");
|
||||
content.innerText = error || (event && event.message) || event || "Unknown Error";
|
||||
inner.appendChild(content);
|
||||
|
||||
var discordLink = document.createElement("p");
|
||||
discordLink.classList.add("discordLink");
|
||||
discordLink.innerHTML =
|
||||
"Please report this error in the <strong>#bugs</strong> channel of the <a href='https://discord.gg/rtuRRJDc7u' target='_blank'>official discord</a>!";
|
||||
|
||||
inner.appendChild(discordLink);
|
||||
|
||||
if (source) {
|
||||
var sourceElement = document.createElement("p");
|
||||
sourceElement.classList.add("source");
|
||||
sourceElement.innerText = source + ":" + lineno + ":" + colno;
|
||||
inner.appendChild(sourceElement);
|
||||
}
|
||||
|
||||
document.documentElement.appendChild(element);
|
||||
}
|
||||
|
||||
window.addEventListener("error", errorHandler);
|
||||
|
||||
function expectJsParsed() {
|
||||
if (!callbackDone) {
|
||||
console.error("👀 Got no core callback");
|
||||
throw new Error("Core thread failed to respond within time.");
|
||||
}
|
||||
}
|
||||
|
||||
function onJsLoaded() {
|
||||
console.log("👀 Core loaded at", Math.floor(performance.now()), "ms");
|
||||
loadTimeout = setTimeout(expectJsParsed, 120000);
|
||||
window.removeEventListener("unhandledrejection", errorHandler);
|
||||
}
|
||||
|
||||
window.coreThreadLoadedCb = function () {
|
||||
console.log("👀 Core responded at", Math.floor(performance.now()), "ms");
|
||||
clearTimeout(loadTimeout);
|
||||
loadTimeout = null;
|
||||
callbackDone = true;
|
||||
};
|
||||
|
||||
function progressHandler(progress) {
|
||||
var progressElement = document.querySelector("#ll_preload_status");
|
||||
if (progressElement) {
|
||||
progressElement.innerText = "Downloading Bundle (" + Math.round(progress * 1200) + " / 1200 KB)";
|
||||
}
|
||||
var barElement = document.querySelector("#ll_progressbar span");
|
||||
if (barElement) {
|
||||
barElement.style.width = (5 + progress * 75.0).toFixed(2) + "%";
|
||||
}
|
||||
}
|
||||
|
||||
function startBundleDownload() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var notifiedNotComputable = false;
|
||||
|
||||
xhr.open("GET", bundleSrc, true);
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.onprogress = function (ev) {
|
||||
if (ev.lengthComputable) {
|
||||
progressHandler(ev.loaded / ev.total);
|
||||
} else {
|
||||
if (!notifiedNotComputable) {
|
||||
notifiedNotComputable = true;
|
||||
console.warn("Progress not computable:", ev);
|
||||
progressHandler(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onloadend = function () {
|
||||
if (!xhr.status.toString().match(/^2/)) {
|
||||
throw new Error("Failed to load bundle: " + xhr.status + " " + xhr.statusText);
|
||||
} else {
|
||||
if (!notifiedNotComputable) {
|
||||
progressHandler(1);
|
||||
}
|
||||
|
||||
var options = {};
|
||||
var headers = xhr.getAllResponseHeaders();
|
||||
var m = headers.match(/^Content-Type\:\s*(.*?)$/im);
|
||||
|
||||
if (m && m[1]) {
|
||||
options.type = m[1];
|
||||
}
|
||||
|
||||
var blob = new Blob([this.response], options);
|
||||
var script = document.createElement("script");
|
||||
script.addEventListener("load", onJsLoaded);
|
||||
script.src = window.URL.createObjectURL(blob);
|
||||
script.type = "text/javascript";
|
||||
script.charset = "utf-8";
|
||||
if (bundleIntegrity) {
|
||||
script.setAttribute("integrity", bundleIntegrity);
|
||||
}
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
console.log("Start bundle download ...");
|
||||
window.addEventListener("load", startBundleDownload);
|
||||
})();
|
||||
Reference in New Issue
Block a user