117 lines
5.3 KiB
JavaScript
117 lines
5.3 KiB
JavaScript
/**
|
|
* Dev-only: boot GameScene, discover a handful of the system's objects,
|
|
* and open the MAP console (depth 80) so a headless screenshot shows the
|
|
* whole feature — left cartography feed (muted loop), the CURRENT SYSTEM /
|
|
* GALAXY(standby) tabs, the system chart (discovered objects on the padded
|
|
* frame, the tether union boundary, the fog of what the tether doesn't
|
|
* cover yet, the ship marker) and the SYSTEM readout (discovery /
|
|
* resources segmented bars + legend).
|
|
*
|
|
* node dev/server.mjs 8082 # static server
|
|
* node dev/shot-firefox.mjs \
|
|
* "http://127.0.0.1:8082/dev/map-shot.html" \
|
|
* "window.__MAP_SHOT ? window.__MAP_SHOT.ready : null" \
|
|
* MAP_SHOT.png 30000
|
|
*
|
|
* The report (top-left) lists console errors + the window's paint state.
|
|
*/
|
|
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);
|
|
|
|
// Capture console errors + uncaught exceptions for the report.
|
|
const errors = [];
|
|
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)));
|
|
window.addEventListener('unhandledrejection', (e) => errors.push(`rejection: ${e.reason}`));
|
|
|
|
const gameConfig = createGameConfig();
|
|
gameConfig.scene = [GameScene];
|
|
const game = new Phaser.Game(gameConfig);
|
|
window.game = game;
|
|
|
|
// The report lives OUTSIDE the canvas — a DOM <pre> the screenshot can
|
|
// always read (headless canvases don't have to cooperate).
|
|
const report = document.createElement('pre');
|
|
report.id = 'report';
|
|
report.style.cssText = 'position:fixed;left:10px;top:10px;z-index:9999;max-width:70%;margin:0;padding:8px 12px;font:13px/1.5 monospace;color:#eaf6ff;background:rgba(6,20,16,0.92);border:1px solid #1b3a5a;white-space:pre-wrap;';
|
|
document.body.appendChild(report);
|
|
const setReport = (lines) => { report.textContent = (Array.isArray(lines) ? lines : [lines]).join('\n'); };
|
|
setReport('booting…');
|
|
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
async function waitScene() {
|
|
for (let i = 0; i < 100; i++) {
|
|
const s = game.scene.getScene('GameScene');
|
|
if (s && s.ship && s.mapWindow) return s;
|
|
await sleep(100);
|
|
}
|
|
throw new Error('GameScene never booted');
|
|
}
|
|
|
|
try {
|
|
const s = await waitScene();
|
|
await sleep(800); // let the boot settle (dossier decode, deck flicker)
|
|
|
|
// Discover a HANDFUL of objects so the chart shows both sides: the
|
|
// discovered (bright, lit segments) and the still-hidden (fog + dark
|
|
// segments). Deterministic picks: the central body (home), the planets,
|
|
// the first station (if any) and the first rock field (if any).
|
|
const sysId = s.systemRecord.id;
|
|
let known = s.discovery.bySystem.get(sysId);
|
|
if (!known) {
|
|
known = new Set();
|
|
s.discovery.bySystem.set(sysId, known);
|
|
}
|
|
const push = (obj) => {
|
|
if (!obj || known.has(obj.id)) return;
|
|
// Discovery.check with the ship "on" the object = discovered, no FX.
|
|
s.discovery.check(sysId, obj.x, obj.y, [obj]);
|
|
};
|
|
if (s.isHomeSystem && s.planet) push({ id: 'home', x: 0, y: 0, radius: s.planet.radius });
|
|
for (const p of s.systemPlanets) push({ id: p.discoveryId, x: p.x, y: p.y, radius: p.radius });
|
|
if (s.systemStations[0]) push({ id: s.systemStations[0].discoveryId, x: s.systemStations[0].x, y: s.systemStations[0].y, radius: s.systemStations[0].bound ?? 60 });
|
|
if (s.asteroidClusters[0]) push({ id: s.asteroidClusters[0].discoveryId, x: s.asteroidClusters[0].x, y: s.asteroidClusters[0].y, radius: s.asteroidClusters[0].bound ?? 100 });
|
|
|
|
// Open the console (the deck MAP button does exactly this).
|
|
s.deckAction('map');
|
|
await sleep(1600); // the boot reveal + first chart paint + font repaint
|
|
|
|
// The locked GALAXY socket: a press must not crash (onLocked toast).
|
|
let locked = 'n/a';
|
|
try {
|
|
const gal = s.mapWindow.tabs.find((t) => t.id === 'galaxy');
|
|
s.mapWindow._tabHit(gal);
|
|
locked = 'press ok';
|
|
} catch (e) { locked = 'press err: ' + e.message; }
|
|
|
|
const win = s.mapWindow;
|
|
const snap = s.mapChartSnapshot?.() ?? null;
|
|
const lines = [
|
|
errors.length === 0 ? 'SMOKE OK — no console errors' : `ERRORS:\n${errors.slice(0, 4).join('\n')}`,
|
|
`window: ${win?.openState} · tabs=${win?.tabs.map((t) => t.id).join(',')}`,
|
|
snap
|
|
? `snapshot: ${snap.objects.length} objects · ${snap.tethers.length} tethers · nav=${snap.stats.nav.found}/${snap.stats.nav.total} · res=${snap.stats.res.found}/${snap.stats.res.total}`
|
|
: 'snapshot: NONE',
|
|
`discovered now: ${s.discovery.discoveredIds(sysId).join(', ') || '—'}`,
|
|
`video: ${win?.video ? (win.video.video?.paused ? 'paused' : 'playing') : 'NO SIGNAL'}`,
|
|
`galaxy tab: ${locked}`,
|
|
`chart tex: ${win?._texKey ?? '—'} · tf scale=${win?._tf ? win._tf.scale.toExponential(2) : '—'}`,
|
|
];
|
|
setReport(lines);
|
|
window.__MAP_SHOT = { ready: true, lines, errors };
|
|
console.info('map-shot: report painted');
|
|
} catch (err) {
|
|
errors.push(`FATAL: ${err.message}`);
|
|
setReport(['FATAL: ' + err.message, ...errors.slice(0, 4)]);
|
|
window.__MAP_SHOT = { ready: true, fatal: String(err.message), errors };
|
|
console.error('map-shot: fatal', err);
|
|
}
|