orbit/dev/quest-ready.mjs

87 lines
3.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Dev-only: the quest tracker's READY state (the "A + C" attract), shot live.
*
* Boots the GameScene (deterministic seed), waits for the open dossier to
* auto-fold (the tracker slides in), then completes the starter quest all
* at once — the flip fires the one-shot moment (flash + ◆ burst) and the
* same-frame repaint goes READY (amber row). `window.__QUEST_READY__` is
* set the instant the burst is still alive, so the capture lands on it:
*
* node dev/server.mjs 8080
* node dev/shot-firefox.mjs http://localhost:8080/dev/quest-ready.html \
* "window.__QUEST_READY__" /tmp/quest-ready.png 45000
*/
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';
import { SurfaceScene } from '../js/scenes/SurfaceScene.js';
const data = await ConfigLoader.load();
config.init(data);
const gameConfig = createGameConfig();
globalThis.__ORBIT_DEV_SEED = '7'; // deterministic galaxy — reproducible shots
// Dev: surface console errors on the flag (a shot with a READY row AND a
// console error is a regression, even if the shot looks fine).
const __errors = [];
if (typeof window !== 'undefined') {
const origErr = console.error.bind(console);
console.error = (...a) => { __errors.push(a.map(String).join(' ')); origErr(...a); };
window.addEventListener('error', (e) => __errors.push(String(e.message)));
}
gameConfig.scene = [GameScene, SurfaceScene];
const game = new Phaser.Game(gameConfig);
window.game = game;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const until = async (fn, ms = 30000) => {
const t0 = Date.now();
for (;;) {
const v = fn();
if (v) return v;
if (Date.now() - t0 > ms) return null;
await sleep(200);
}
};
setTimeout(async () => {
try {
const s = await until(() => (game.scene.getScene('GameScene')?.questTracker ? game.scene.getScene('GameScene') : null));
if (!s) { window.__QUEST_READY__ = { error: 'scene never became ready' }; return; }
// Wait for the open dossier to auto-fold → the tracker slides in
// (the tracker's first poll establishes its READY baseline while the
// quest is still open, so the flip below is a true transition).
await until(() => s.questTracker.shown === true);
await sleep(250); // let the slide fully settle
// Complete the starter quest (all four checks), live — the flip:
s.totalMined = 200;
s.researchState.isUnlocked = (cat, node) => true;
s.tetherLevelFor = (name) => 2;
s.discoveredWorldCount = () => 1;
s._questRefresh(); // toast + chime + tracker repaint (the same frame)
await sleep(380); // inside the burst's life (700–1000 ms) — catch the glyphs
const snap = s.questSnapshot();
const q = snap.quests.find((x) => x.id === 'start_your_journey');
window.__QUEST_READY__ = {
trackerShown: s.questTracker.shown,
questComplete: q?.complete === true,
questClaimed: q?.claimed === true,
baselineHasStarter: s.questTracker._readyBaseline?.has('start_your_journey') === true,
errors: __errors.slice(0, 3),
};
// This geckodriver can't read the flag back (execute/sync → null), so
// paint the verdict on the canvas too — the screenshot IS the readout.
s.add.text(16, 690, `READY-FLAG ${JSON.stringify(window.__QUEST_READY__)}`,
{ fontFamily: 'monospace', fontSize: '11px', color: '#7ce8a4', align: 'left' })
.setOrigin(0, 1).setScrollFactor(0).setDepth(9000);
} catch (err) {
window.__QUEST_READY__ = { error: String(err?.stack ?? err) };
}
}, 400);