Remove conversions for old saves (t83)
This commit is contained in:
+2
-2
@@ -392,8 +392,8 @@ Dev commands are pure simulation operations; the browser owns the panel and conf
|
||||
- functions: resetDevConsole, enableDevConsole, devError, devName, devGiveable, devMaterialList, devDistance, devSuggestions, devHistory, devRemember, devRecall, devComplete, devMaterial, devCommand
|
||||
- variables: devWorld, devLog, devFree, devSpeed, devPaused, devSteps, DEV_COMMANDS, DEV_MATERIALS
|
||||
|
||||
### src/sim/save.js (216 lines)
|
||||
Saving and loading a world (serializeWorld / deserializeWorld) and old-save migration.
|
||||
### src/sim/save.js (201 lines)
|
||||
Saving and loading a world (serializeWorld / deserializeWorld).
|
||||
- functions: serializeWorld, deserializeWorld, startLoadWake, wakeLoadArea, wakeLoadNearBot, loadWakeTick
|
||||
- variables: SAVE_VERSION, TOFF
|
||||
|
||||
|
||||
@@ -4,6 +4,16 @@ What agents have done, newest first. Add an entry for every piece of work: the d
|
||||
note or request it was for, what changed, the files touched, the tests run, and anything left
|
||||
open or not verified. Keep each entry short; the git history has the details.
|
||||
|
||||
## 2026-10-29: t83 remove old-save conversions (Codex)
|
||||
|
||||
- Removed only spring, solid-pipe, single-material-filter and foreground-tree conversions
|
||||
from `src/sim/save.js`; world generation and its spring random draws are untouched.
|
||||
- Files: save.js, test/t_{load,weather,conveyors}.js, docs/PROJECT_MAP.md, tasks/t83*.
|
||||
Three expectations failed first; updated obsolete spring/filter migration tests deliberately.
|
||||
- All 41 headless suites pass; pixel `test/play.py shots/t83-play` passes with no console
|
||||
errors. Sandbox lacked WebGPU; host GPU rerun passed. Inspected saving-progress.png and
|
||||
10-after.png (saved/reloaded world). Map regenerated; nothing left open.
|
||||
|
||||
## 2026-10-29: t81 shared piece direction variants (Codex)
|
||||
|
||||
- `pieceV` accepts a direction and resolved code; `dragPlan` calls it for previews and
|
||||
|
||||
+1
-16
@@ -1,4 +1,4 @@
|
||||
// Saving and loading a world (serializeWorld / deserializeWorld) and old-save migration.
|
||||
// Saving and loading a world (serializeWorld / deserializeWorld).
|
||||
// ---------- Save / load ----------
|
||||
const SAVE_VERSION = 2;
|
||||
const TOFF = 64; // temperatures are saved with an offset so sub-zero snow and ice survive
|
||||
@@ -60,7 +60,6 @@ function deserializeWorld(meta, buffers) {
|
||||
mat.set(buffers.mat); life.set(buffers.life); flags.set(buffers.flags);
|
||||
for (let i = 0; i < N; i++) {
|
||||
if (mat[i] >= NMAT) mat[i] = EMPTY;
|
||||
else if (mat[i] === SPRING) mat[i] = STONE; // springs are gone: older worlds keep plain rock there
|
||||
}
|
||||
blockP.set(buffers.blockP); blockV.set(buffers.blockV); filtersDirty = true;
|
||||
for (let b = 0; b < NB; b++) {
|
||||
@@ -81,22 +80,8 @@ function deserializeWorld(meta, buffers) {
|
||||
}
|
||||
s.open = open === true; rackState.set(b, s);
|
||||
}
|
||||
// pipes used to be solid copper blocks; now they are thin and let things past
|
||||
for (let b = 0; b < NB; b++) if (blockP[b] === BP_PIPE) for (const i of blockCellList(b % BW, (b / BW) | 0)) if (mat[i] === PIPE) { mat[i] = EMPTY; part[i] = P_PIPE; }
|
||||
for (const [b, m, inv] of meta.filters || []) if (isFilter(blockP[b])) filterCfg.set(b, filterRec({ m, inv }));
|
||||
for (let b = 0; b < NB; b++) if (isFilter(blockP[b])) {
|
||||
// the first filters kept one material in their block variant
|
||||
if (!filterCfg.has(b)) filterCfg.set(b, filterRec({ m: [blockV[b] & 127], inv: 0 }));
|
||||
blockV[b] &= 128;
|
||||
}
|
||||
if (buffers.bgm) { bgm.set(buffers.bgm); }
|
||||
else {
|
||||
// older saves kept trees in the foreground: move them behind
|
||||
for (let i = 0; i < N; i++) {
|
||||
const m = mat[i], y = (i / W) | 0;
|
||||
if (m === LEAVES || (m === WOOD && (flags[i] & F_NAT) && y < surfY[i % W])) { bgm[i] = m; mat[i] = EMPTY; flags[i] = 0; }
|
||||
}
|
||||
}
|
||||
const t16 = buffers.temp, off = meta.tOff || 0; for (let i = 0; i < N; i++) temp[i] = t16[i] / 16 - off;
|
||||
saplings = (meta.saplings || []).map(([x, y, age, th, seed]) => ({ x, y, age, th, seed }));
|
||||
findTreeBases();
|
||||
|
||||
+2
-2
@@ -199,9 +199,9 @@ run('clearAllGhosts(); pasteGhost(flipBlueprint(copyRegion(120, 100, 123, 103)),
|
||||
check('pasting it builds a filter with the same materials and mode', run('blockP[25*BW+34]') === run('BP_FILTER') && run('JSON.stringify(filterInfo(25*BW+34))') === JSON.stringify({ m: [run('CUORE'), run('FEORE')].sort((a, b) => a - b), inv: 1 }), run('JSON.stringify(filterInfo(25*BW+34))'));
|
||||
run('globalThis.__s = serializeWorld(); deserializeWorld(__s.meta, __s.buffers);');
|
||||
check('save and load keep filters, their materials, mode and direction', run('blockP[25*BW+30]') === run('BP_FILTER') && run('blockV[25*BW+30]') === 128 && run('filterInfo(25*BW+30).inv') === 1 && run('filterInfo(25*BW+30).m.length') === 2 && run('part[100*W+120]') === run('P_FILTER'));
|
||||
// a save from before: one material kept in the block variant
|
||||
// A retired single-material variant is no longer reconstructed on load.
|
||||
run('__s.meta.filters = []; __s.buffers.blockV[25*BW+30] = 128 | SAND; deserializeWorld(__s.meta, __s.buffers);');
|
||||
check('older filters keep the one material they had', run('JSON.stringify(filterInfo(25*BW+30))') === JSON.stringify({ m: [run('SAND')], inv: 0 }) && run('blockV[25*BW+30]') === 128);
|
||||
check('loading does not reconstruct retired single-material filters', run('!filterCfg.has(25*BW+30) && blockV[25*BW+30] === (128 | SAND)'));
|
||||
// the run of matching filters in a row
|
||||
fresh();
|
||||
run('for (let bx = 20; bx < 26; bx++) placeBlock(BP_FILTER, 128, bx, 25, true, { m: [SAND] }); placeBlock(BP_FILTER, 128, 26, 25, true, { m: [COAL] }); placeBlock(BP_FILTER, 0, 27, 25, true, { m: [COAL] });');
|
||||
|
||||
@@ -51,6 +51,29 @@ for (const [label, doctor, clean] of [
|
||||
})()`));
|
||||
}
|
||||
|
||||
// Retired save formats are no longer translated into current construction or trees.
|
||||
flatWorld(run, 256, 256, 200);
|
||||
run(`
|
||||
placeBlock(BP_FILTER, 128, 5, 10, true, { m: [SAND, COAL], inv: 1 });
|
||||
placeBlock(BP_PIPE, 0, 8, 10, true);
|
||||
bgm[100 * W + 40] = LEAVES;
|
||||
globalThis.currentSave = serializeWorld();
|
||||
deserializeWorld(currentSave.meta, currentSave.buffers);
|
||||
`);
|
||||
check('current filter settings and direction survive loading', run('blockV[10 * BW + 5] === 128 && JSON.stringify(filterCfg.get(10 * BW + 5)) === JSON.stringify(filterRec({ m: [SAND, COAL], inv: 1 }))'));
|
||||
check('current thin pipes and background trees survive loading', run('part[40 * W + 32] === P_PIPE && mat[40 * W + 32] === EMPTY && bgm[100 * W + 40] === LEAVES'));
|
||||
run(`
|
||||
currentSave.meta.filters = [];
|
||||
currentSave.buffers.blockV[10 * BW + 5] = 128 | SAND;
|
||||
delete currentSave.buffers.bgm;
|
||||
currentSave.buffers.mat[100 * W + 40] = LEAVES;
|
||||
currentSave.buffers.mat[110 * W + 40] = WOOD;
|
||||
currentSave.buffers.flags[110 * W + 40] = F_NAT;
|
||||
deserializeWorld(currentSave.meta, currentSave.buffers);
|
||||
`);
|
||||
check('loading does not invent a filter setting from its old block variant', run('!filterCfg.has(10 * BW + 5) && blockV[10 * BW + 5] === (128 | SAND)'));
|
||||
check('loading does not move foreground trees into a missing background layer', run('mat[100 * W + 40] === LEAVES && mat[110 * W + 40] === WOOD && flags[110 * W + 40] === F_NAT && bgm[100 * W + 40] === EMPTY && bgm[110 * W + 40] === EMPTY'));
|
||||
|
||||
flatWorld(run, 1024, 256, 200);
|
||||
run(`
|
||||
bot.x = 510; bot.y = 170;
|
||||
|
||||
+2
-2
@@ -8,9 +8,9 @@ const rainInAir = (m) => run(`flyers.filter(f => f.rain && f.m === ${m}).length`
|
||||
run('generateWorld(777, 1024, 640, null)');
|
||||
check('new worlds have no springs', count(run, run('SPRING')) === 0);
|
||||
check('and the same seed still makes the same land', run('surfY[512]') > 0 && run('!!dock()'));
|
||||
// an older save with a spring in it: the spring becomes plain rock
|
||||
// Loading no longer converts retired spring cells to rock.
|
||||
run('globalThis.__s = serializeWorld(); __s.buffers.mat[300 * W + 500] = SPRING; deserializeWorld(__s.meta, __s.buffers);');
|
||||
check('springs in older worlds turn into plain rock', run('mat[300 * W + 500]') === run('STONE') && count(run, run('SPRING')) === 0);
|
||||
check('loading leaves retired spring cells unchanged', run('mat[300 * W + 500]') === run('SPRING') && count(run, run('SPRING')) === 1);
|
||||
|
||||
// steam in the open sky rises into the clouds instead of condensing
|
||||
flatWorld(run, 320, 200, 120);
|
||||
|
||||
Reference in New Issue
Block a user