145 lines
5.9 KiB
JavaScript
145 lines
5.9 KiB
JavaScript
/**
|
|
* Dev: the UPGRADED CARGO HOLD survives a gate JUMP (v0.5):
|
|
*
|
|
* The bar scene's DONE beat builds the hold out (GameScene.
|
|
* onVignetteComplete: effects.cargoHold, then the 'special-package'
|
|
* in it). The hold is SHIP STATE — so it must ride every transport.
|
|
* A gate jump is its own transport: jumpThroughGate re-stages the run
|
|
* through the save pipeline (captureState → rec.ship → prepareLoad →
|
|
* scene.restart → applyRestore on a FRESH ship, which starts at the
|
|
* 0-bay baseline — data/ship.json).
|
|
*
|
|
* This test proves the beat survives that hop end-to-end with the
|
|
* REAL jumpThroughGate (no stubs):
|
|
*
|
|
* 1. fresh VESTRA run → 0 bays, empty hold (the baseline)
|
|
* 2. stage the beat → 4 bays, 'special-package' aboard
|
|
* 3. real jump through an ACTIVE gate → the scene restarts onto the
|
|
* destination system
|
|
* 4. the FRESH ship after the jump keeps the bays (cargoHold 4,
|
|
* capacity 4) AND the package (the jump's rec.ship carries
|
|
* cargoHold; without it the restore would re-seed the 0 baseline
|
|
* and shed the goods)
|
|
*
|
|
* node dev/server.mjs 8099
|
|
* node dev/cdp-firefox.mjs http://localhost:8099/dev/jump-cargo.html \
|
|
* 'return window.__JUMP_CARGO__;' 90000
|
|
*/
|
|
import Phaser from '../js/vendor/phaser.js';
|
|
import { config } from '../js/config/Config.js';
|
|
import { ConfigLoader } from '../js/config/ConfigLoader.js';
|
|
import { createGameConfig } from '../js/config/GameConfig.js';
|
|
import { GameScene } from '../js/scenes/GameScene.js';
|
|
|
|
const data = await ConfigLoader.load();
|
|
config.init(data);
|
|
|
|
// 'VESTRA's starting system holds three gates (the gate-comms seed).
|
|
globalThis.__ORBIT_DEV_SEED = 'VESTRA';
|
|
const gameConfig = createGameConfig();
|
|
gameConfig.scene = [GameScene]; // GameScene boots first
|
|
if (typeof Phaser !== 'undefined') Phaser.NoAudioContext = true;
|
|
|
|
const game = new Phaser.Game(gameConfig);
|
|
window.game = game;
|
|
|
|
/* ---- helpers (the gate-comms harness pattern) ------------------------- */
|
|
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
/** Pump the loop until `ok()` or the budget elapses. */
|
|
async function pump(s, ok, ms = 4000) {
|
|
const t0 = Date.now();
|
|
while (!ok() && Date.now() - t0 < ms) {
|
|
s.game.loop.step(performance.now());
|
|
await sleep(0);
|
|
}
|
|
return ok();
|
|
}
|
|
|
|
async function ready() {
|
|
const t0 = Date.now();
|
|
for (;;) {
|
|
const g = window.game;
|
|
const s = g && g.scene?.getScene?.('GameScene');
|
|
if (s && s.sys?.isActive && s.ship && (s.systemGates?.length ?? 0) >= 1) return s;
|
|
if (Date.now() - t0 > 45000) throw new Error('game never became ready');
|
|
await sleep(50);
|
|
}
|
|
}
|
|
|
|
/* ---- the test ---------------------------------------------------------- */
|
|
|
|
async function run() {
|
|
const out = { steps: [] };
|
|
const step = (name, pass, extra = {}) => out.steps.push({ name, pass, ...extra });
|
|
const s = await ready();
|
|
|
|
s.cameraFollowShip = false;
|
|
s.hideHint?.();
|
|
s.ship.stop();
|
|
const gateA = s.systemGates[0];
|
|
|
|
// ---- 1. the fresh baseline ---------------------------------------------
|
|
step('a fresh ship starts at the 0-bay baseline (data/ship.json)',
|
|
s.ship.stats.cargoHold === 0 && s.ship.cargo.capacity === 0 && s.ship.cargo.items.length === 0);
|
|
|
|
// ---- 2. stage the beat (the bar scene's DONE press, verbatim) -----------
|
|
s.ship.setCargoHold(4); // GameScene.onVignetteComplete: effects.cargoHold
|
|
s.ship.cargo.add('special-package'); // then the quest's package
|
|
step('the beat is live (4 bays, the package aboard)',
|
|
s.ship.stats.cargoHold === 4 && s.ship.cargo.capacity === 4
|
|
&& s.ship.cargo.has('special-package') === true);
|
|
|
|
// Keep the ship OUT of the gate's keepout (solid — the ship can't
|
|
// overlap it) before the jump re-stages the run.
|
|
s.ship.x = gateA.x + 2500;
|
|
s.ship.y = gateA.y + 2000;
|
|
|
|
// ---- 3. the REAL jump (no stubs) -----------------------------------------
|
|
gateA.active = true; // (the research tech would do this — same flag)
|
|
const destId = gateA.gate?.to;
|
|
const beforeShip = s.ship;
|
|
step('the jump target is a known system',
|
|
!!destId && s.galaxy.byId.has(destId) === true);
|
|
const fromSystem = s.galaxy.currentSystemId;
|
|
s.jumpThroughGate(gateA);
|
|
|
|
// The cut: jump clip (or its stall guard) → _finishJump → scene.restart
|
|
// → a FRESH scene on the destination. The scene INSTANCE survives
|
|
// (restart), but this.ship is a new object — that is the restart tell.
|
|
// applyRestore runs at the END of create(), so wait for the beat to
|
|
// be back on the fresh ship (cargoHold restored + package aboard).
|
|
const restored = await pump(
|
|
s,
|
|
() => s.ship !== beforeShip
|
|
&& s.ship.stats.cargoHold === 4
|
|
&& s.ship.cargo.has('special-package') === true,
|
|
30000,
|
|
);
|
|
step('the jump completed (the scene restarted onto the destination)',
|
|
s.ship !== beforeShip && game.scene.isActive('GameScene'));
|
|
step('the ship is in the destination system',
|
|
s.galaxy.currentSystemId === destId && s.galaxy.currentSystemId !== fromSystem);
|
|
|
|
// ---- 4. the beat survived the hop ----------------------------------------
|
|
step('THE BEAT SURVIVES THE JUMP: the fresh ship keeps the bays (cargoHold 4, capacity 4)',
|
|
!!restored && s.ship.stats.cargoHold === 4 && s.ship.cargo.capacity === 4,
|
|
{ cargoHold: s.ship?.stats?.cargoHold, capacity: s.ship?.cargo?.capacity });
|
|
step('THE BEAT SURVIVES THE JUMP: the package is still aboard',
|
|
!!restored && s.ship.cargo.has('special-package') === true
|
|
&& JSON.stringify(s.ship.cargo.items) === JSON.stringify(['special-package']),
|
|
{ items: s.ship?.cargo?.items });
|
|
|
|
out.pass = out.steps.every((st) => st.pass);
|
|
return out;
|
|
}
|
|
|
|
window.__JUMP_CARGO__ = null;
|
|
run()
|
|
.then((out) => { window.__JUMP_CARGO__ = out; console.log(out.pass ? 'JUMP-CARGO PASS' : 'JUMP-CARGO FAIL'); })
|
|
.catch((err) => {
|
|
console.error(err);
|
|
window.__JUMP_CARGO__ = { pass: false, steps: [{ name: `DRIVER CRASHED: ${err.message}`, pass: false }] };
|
|
});
|