160 lines
5.4 KiB
JavaScript
160 lines
5.4 KiB
JavaScript
"use strict";
|
|
|
|
function ensureWorldBootstrap() {
|
|
let currentWorld = globalThis.world;
|
|
if (currentWorld?.update) return currentWorld;
|
|
try {
|
|
currentWorld = new World();
|
|
if (typeof window !== "undefined") window.world = currentWorld;
|
|
if (typeof globalThis !== "undefined") globalThis.world = currentWorld;
|
|
return currentWorld;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
let world = ensureWorldBootstrap();
|
|
let last = nowSec();
|
|
let statsTimer = 0;
|
|
let statsRefreshPending = false;
|
|
window.__tarinaiFps = 0;
|
|
|
|
function scheduleStatsRefresh() {
|
|
if (statsRefreshPending) return;
|
|
if (typeof colonyStatsUiVisible === "function" && !colonyStatsUiVisible()) return;
|
|
statsRefreshPending = true;
|
|
const run = () => {
|
|
statsRefreshPending = false;
|
|
if (!document.hidden) renderStats();
|
|
};
|
|
if (typeof window.requestIdleCallback === "function") window.requestIdleCallback(run, { timeout: 900 });
|
|
else window.setTimeout(run, 0);
|
|
}
|
|
|
|
const LOADING_SPRITES = SPRITES
|
|
.filter(asset => asset && !asset.actionOnly)
|
|
.slice(0, 11)
|
|
.map(asset => asset.path);
|
|
let loadingSpriteTimer = 0;
|
|
|
|
function shuffledLoadingSprites() {
|
|
const list = [...LOADING_SPRITES];
|
|
for (let i = list.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[list[i], list[j]] = [list[j], list[i]];
|
|
}
|
|
return list.slice(0, 4);
|
|
}
|
|
|
|
function renderLoadingSprites() {
|
|
const strip = document.getElementById("loadingSpriteStrip");
|
|
if (!strip) return;
|
|
strip.innerHTML = "";
|
|
const frag = document.createDocumentFragment();
|
|
for (const src of shuffledLoadingSprites()) {
|
|
const card = document.createElement("div");
|
|
card.className = "loading-sprite-card";
|
|
const img = document.createElement("img");
|
|
img.src = src;
|
|
img.alt = "";
|
|
img.loading = "eager";
|
|
card.appendChild(img);
|
|
frag.appendChild(card);
|
|
}
|
|
strip.appendChild(frag);
|
|
}
|
|
|
|
function initLoadingShowcase() {
|
|
renderLoadingSprites();
|
|
if (loadingSpriteTimer) clearInterval(loadingSpriteTimer);
|
|
loadingSpriteTimer = window.setInterval(renderLoadingSprites, 1200);
|
|
}
|
|
|
|
|
|
function setLoadingProgress(text = "", ratio = 0) {
|
|
const screen = document.getElementById("loadingScreen");
|
|
if (!screen) return;
|
|
const pct = clamp(Number(ratio) || 0, 0, 1);
|
|
const label = document.getElementById("loadingText");
|
|
const bar = document.getElementById("loadingBar");
|
|
const percent = document.getElementById("loadingPercent");
|
|
if (label && text) label.textContent = text;
|
|
if (bar) bar.style.width = `${Math.round(pct * 100)}%`;
|
|
if (percent) percent.textContent = `${Math.round(pct * 100)}%`;
|
|
}
|
|
|
|
function hideLoadingScreen() {
|
|
if (loadingSpriteTimer) { clearInterval(loadingSpriteTimer); loadingSpriteTimer = 0; }
|
|
document.getElementById("loadingSpriteStrip")?.replaceChildren();
|
|
setLoadingProgress("\u8d77\u52d5\u5b8c\u4e86", 1);
|
|
const screen = document.getElementById("loadingScreen");
|
|
if (!screen) return;
|
|
window.setTimeout(() => screen.classList.add("hidden"), 120);
|
|
}
|
|
function loop() {
|
|
const t = nowSec();
|
|
const rawDt = t - last;
|
|
const dt = clamp(rawDt, 0, 0.05);
|
|
last = t;
|
|
window.TarinaiPerf.observeFrameDelta(rawDt);
|
|
window.TarinaiPerf.beginFrame();
|
|
const endUpdate = window.TarinaiPerf.begin("update.total");
|
|
world.update(dt);
|
|
if (typeof tickColonyHistorySampling === "function") tickColonyHistorySampling();
|
|
if (endUpdate) endUpdate();
|
|
const endRender = window.TarinaiPerf.begin("render.total");
|
|
render();
|
|
if (endRender) endRender();
|
|
window.TarinaiPerf.endFrame();
|
|
if (window.TarinaiPerf.consumeResizeRequest() && typeof resizeCanvas === "function") resizeCanvas();
|
|
statsTimer += dt;
|
|
const statsInterval = 2.5;
|
|
if (statsTimer > statsInterval) {
|
|
scheduleStatsRefresh();
|
|
statsTimer = 0;
|
|
}
|
|
requestAnimationFrame(loop);
|
|
}
|
|
|
|
initLoadingShowcase();
|
|
setLoadingProgress("\u521d\u671f\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307f\u4e2d", 0.08);
|
|
loadImages((done, total) => {
|
|
const p = total > 0 ? done / total : 1;
|
|
setLoadingProgress(`\u521d\u671f\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307f\u4e2d ${done}/${total}`, 0.08 + p * 0.46);
|
|
}).then(() => {
|
|
setLoadingProgress("UI\u3092\u6e96\u5099\u4e2d", 0.62);
|
|
bindUI();
|
|
setLoadingProgress("\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u69cb\u7bc9\u4e2d", 0.72);
|
|
applyFieldLayout("garden");
|
|
world.reset(null, "garden");
|
|
window.TarinaiGroundUI?.bind?.(world);
|
|
selectTool("observe");
|
|
setLoadingProgress("\u8868\u793a\u3092\u521d\u671f\u5316\u4e2d", 0.84);
|
|
renderLog(world.logs);
|
|
renderArchive();
|
|
render();
|
|
renderStats();
|
|
syncTopButtons();
|
|
startBackgroundImageLoading();
|
|
setLoadingProgress("\u30b7\u30df\u30e5\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u958b\u59cb\u4e2d", 0.94);
|
|
loop();
|
|
requestAnimationFrame(hideLoadingScreen);
|
|
});
|
|
|
|
if ("serviceWorker" in navigator) {
|
|
window.addEventListener("load", () => {
|
|
const swUrl = window.TARINAI_APP?.withVersion?.("./service-worker.js") || "./service-worker.js";
|
|
navigator.serviceWorker.register(swUrl, { updateViaCache: "none" }).catch(() => undefined);
|
|
});
|
|
}
|
|
|
|
|
|
// Expose the active build on the root element so stale-cache reports can be verified immediately.
|
|
(function markActiveBuild() {
|
|
const apply = () => {
|
|
if (!document?.documentElement) return;
|
|
document.documentElement.dataset.tarinaiBuild = String(window.TARINAI_APP?.build || window.TARINAI_VERSION || "unknown");
|
|
};
|
|
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply, { once: true });
|
|
else apply();
|
|
})();
|