Progress bar and steps while generating, loading, opening claims and travelling; saving chip (t30)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 18:54:06 -04:00
co-authored by Claude Opus 5.5
parent e3280b7b1e
commit 54af0e51ad
14 changed files with 174 additions and 39 deletions
+30 -6
View File
@@ -1,6 +1,12 @@
// Starting, loading and quitting a game; modal dialogs; the pause menu.
// ---------- Start / stop ----------
function showLoading(on, p) {
function showLoading(on, p, label, title) {
GAME.loading = on;
if (on) {
$('saving').hidden = true;
if (title) $('loading').querySelector('.label').textContent = title;
$('loadstep').textContent = label || '';
}
$('loading').hidden = !on;
if (on) { $('loadbar').style.width = Math.round((p || 0) * 100) + '%'; $('loadtext').textContent = Math.round((p || 0) * 100) + '%'; }
}
@@ -15,11 +21,11 @@ function enterGame() {
GAME.drag = null; GAME.lmb = GAME.rmb = false; lastBagKey = '';
hudDirty = true; renderHotbar();
}
async function setupNewWorld(seed, w, h, name, carried) {
auInit(); showLoading(true, 0);
async function setupNewWorld(seed, w, h, name, carried, title = 'Generating world') {
auInit(); showLoading(true, 0, 'Shaping the land', title);
await new Promise(resolve => setTimeout(resolve, 30));
for (const k of Object.keys(stats)) stats[k] = 0;
generateWorld(seed, w, h, null);
await generateWorldAsync(seed, w, h, (f, s) => showLoading(true, f * 0.9, s, title));
GAME.worldId = newWorldId(); GAME.worldName = name;
GAME.playTime = 0; GAME.clip = null; GAME.paste = false; GAME.selDrag = null; GAME.tool = 0; GAME.blow.clear(); GAME.wallMat = RSTONE; GAME.filterCfg = { m: [], inv: 0 }; GAME.pieceIdx = 0;
if (carried) applyCareerState(carried);
@@ -30,30 +36,48 @@ async function startNewWorld(seed, w, h, name = '') {
await setupNewWorld(seed, w, h, cleanWorldName(name, `World ${worlds.length + 1}`));
career = { id: newWorldId(), claims: [GAME.worldId], claimNo: 1 };
GAME.careerId = career.id; GAME.claimNo = 1;
showLoading(true, 0.9, 'Saving');
await saveWorld('auto');
showLoading(true, 1, 'Saving');
showLoading(false); closeAllModals(); enterGame();
showCard({ kind: 'Welcome', title: 'The dig site', body: ['Fly with WASD. The Drill (1) breaks rock loose. The Pneumatic nozzle (2) picks up and blows the selection. Click or Q/E in the bag selects; Ctrl+click mixes. Hold Ctrl to see everything found. Clear returns to picking what you click. Shift: everything.', 'You owe $20,000 on this claim. Sell what you dig and make at the trade dock next to you: anything that drops through its grate is paid for on the spot, and buyers post orders that pay far more. Every tip lives in the notebook (N).'], hold: 1.8 });
} catch (e) { showLoading(false); toast('Could not create a world. Browser storage is unavailable.'); }
}
async function startFromSave(sv) {
async function startFromSave(sv, onProgress) {
onProgress = onProgress || ((f, s) => showLoading(true, f, s, 'Loading world'));
auInit();
GAME.paused = true;
try {
for (const k of Object.keys(stats)) stats[k] = 0;
onProgress(0.75, 'Building the world');
await new Promise(r => setTimeout(r, 30));
deserializeWorld(sv.meta, sv.buffers);
}
catch (e) {
toast(e && e.message ? e.message : 'That save could not be loaded.', { big: true, title: 'Save not loaded' });
showLoading(false);
GAME.running = false; $('hud').hidden = true; $('title').hidden = false; if (!TITLE.raf) drawTitle();
return false;
}
GAME.worldId = sv.worldId || ''; GAME.worldName = sv.worldName || '';
GAME.playTime = sv.playTime || 0;
GAME.drag = null; GAME.blow.clear();
onProgress(0.95, 'Your gear and notebook');
await loadCareer();
showLoading(false);
enterGame();
return true;
}
async function loadSavedWorld(id) {
const progress = (f, s) => showLoading(true, f, s, 'Loading world');
progress(0, 'Reading the save');
try {
const sv = id ? await worldNewest(id, progress) : await newestSave(progress);
if (sv) return await startFromSave(sv, progress);
toast('No saved world found.'); return false;
} catch (e) { toast('Could not reach browser storage.'); return false; }
finally { showLoading(false); }
}
async function quitToTitle() {
await saveWorld('main', true);
GAME.running = false; closeAllModals();
@@ -119,7 +143,7 @@ async function renderWorlds(editId) {
button('Save', async () => { await renameWorld(w.id, input.value); await renderWorlds(); await refreshContinue(); });
button('Cancel', () => renderWorlds());
} else {
button('Load', async () => { const sv = await worldNewest(w.id); if (sv && await startFromSave(sv)) closeAllModals(); else if (!sv) toast('No saved world found.'); });
button('Load', async () => { const ok = await loadSavedWorld(w.id); if (ok) closeAllModals(); });
button('Rename', () => renderWorlds(w.id));
button('Delete', () => dialog('Delete world?', `<p class="note">Delete ${esc(w.name)} and its autosave? Exported world files are not affected.</p>`, [
{ label: 'Cancel', cls: 'ghost' },