Reject blueprint codes with unknown pieces, machines or molds (t78)

This commit is contained in:
2026-10-29 17:50:07 -04:00
parent f7c989db6c
commit 5e26e4634d
3 changed files with 82 additions and 1 deletions
+61
View File
@@ -0,0 +1,61 @@
// Shared blueprint codes must be safe before entering the clipboard or ghost queues.
const fs = require('fs');
const path = require('path');
const { load, suite, flatWorld } = require('./harness');
const { run } = load(), { check, done } = suite();
for (const file of ['saves.js', 'notebook-blueprints.js']) {
run(fs.readFileSync(path.join(__dirname, '../src/ui', file), 'utf8'));
}
flatWorld(run, 128, 128, 112);
run(`
globalThis.goodBlueprint = {
v: 2, bw: 8, bh: 8,
blocks: [[0, 0, BP_WALL, RSTONE]],
machines: [['fan', 1, 0, 0]],
molds: [['ingot', 0, 2, RSTONE]]
};
globalThis.GAME = { clip: null, paste: false };
globalThis.hudDirty = false;
globalThis.elements = { 'bp-import': {}, 'bp-paste': { value: '' } };
globalThis.$ = id => elements[id] || null;
globalThis.localStorage = { getItem: () => null };
globalThis.esc = s => s;
globalThis.toast = message => { globalThis.lastToast = message; };
globalThis.closeAllModals = () => {};
globalThis.dialog = (title, html, buttons) => { globalThis.importBlueprint = buttons[1].fn; };
renderBlueprintTab({ innerHTML: '', querySelectorAll: () => [] });
elements['bp-import'].onclick();
`);
check('a good blueprint code round-trips unchanged', run('JSON.stringify(bpDecode(bpEncode(goodBlueprint))) === JSON.stringify(goodBlueprint)'));
check('a good decoded blueprint has a build cost', run('bpCost(bpDecode(bpEncode(goodBlueprint))).length > 0'));
check('block-only codes still allow omitted machine and mold lists', run(`
(() => { const bp = bpDecode(bpEncode({ v: 2, bw: 1, bh: 1, blocks: [[0, 0, BP_WALL, RSTONE]] }));
return bp.machines.length === 0 && bp.molds.length === 0; })()
`));
for (const [name, damage] of [
['unknown piece 250', 'bp.blocks[0][2] = 250'],
['array property used as a piece code', "bp.blocks[0][2] = 'length'"],
['unknown machine', "bp.machines[0][0] = 'unknown-machine'"],
['block used as a machine', "bp.machines[0][0] = 'wall'"],
['fixed trade dock', "bp.machines[0][0] = 'dock'"],
['unknown mold', "bp.molds[0][0] = 'unknown-mold'"],
['inherited mold name', "bp.molds[0][0] = 'toString'"],
]) {
run(`{
clearAllGhosts(); GAME.clip = null; GAME.paste = false;
const bp = JSON.parse(JSON.stringify(goodBlueprint)); ${damage};
globalThis.damagedBlueprint = bp;
elements['bp-paste'].value = bpEncode(bp);
importBlueprint();
if (GAME.paste && GAME.clip) pasteGhost(GAME.clip, 2, 2);
}`);
check(`${name} fails validation`, run('!bpValid(damagedBlueprint)'));
check(`${name} shows the damaged message`, run("lastToast === 'That code is damaged.'"));
check(`${name} leaves the clipboard and paste mode empty`, run('GAME.clip === null && !GAME.paste'));
check(`${name} pastes nothing`, run('ghostBlocks.size === 0 && ghostMachines.length === 0 && ghostMolds.length === 0'));
}
run(`clearAllGhosts(); elements['bp-paste'].value = bpEncode(goodBlueprint); importBlueprint();
if (GAME.paste && GAME.clip) pasteGhost(GAME.clip, 2, 2);`);
check('a good code still imports and pastes all three piece kinds', run('GAME.paste && ghostBlocks.size === 1 && ghostMachines.length === 1 && ghostMolds.length === 1'));
done();