155 lines
6.2 KiB
JavaScript
155 lines
6.2 KiB
JavaScript
/**
|
|
* Dev-only: boot GameScene, set a DESTINATION (a far star's first planet),
|
|
* and open the MAP console's GALAXY tab so a headless screenshot shows:
|
|
* · the route (the active SET DESTINATION path) in ORANGE on the lanes,
|
|
* · the destination star circled in orange,
|
|
* · the compass's route gate (orange, full-sized).
|
|
*
|
|
* node dev/server.mjs 8083 # static server
|
|
* node dev/shot-firefox.mjs \
|
|
* "http://127.0.0.1:8083/dev/route-shot.html" \
|
|
* "window.__ROUTE_SHOT ? window.__ROUTE_SHOT.ready : null" \
|
|
* ROUTE_SHOT.png 40000
|
|
*
|
|
* The report (top-left) lists console errors + the route 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
|
|
|
|
// Pick a FAR destination: the furthest star from the current system
|
|
// (a multi-hop route, so the orange path is visible on several lanes).
|
|
const sysId = s.systemRecord.id;
|
|
const records = s.galaxy.records;
|
|
const cur = records.find((r) => r.id === sysId);
|
|
const others = records.filter((r) => r.id !== sysId);
|
|
others.sort((a, b) => {
|
|
const da = Math.hypot(a.x - cur.x, a.y - cur.y);
|
|
const db = Math.hypot(b.x - cur.x, b.y - cur.y);
|
|
return db - da; // farthest first
|
|
});
|
|
// Use the 3rd-furthest (leave some margin so the route is a real path,
|
|
// not a single hop).
|
|
const dest = others[2] ?? others[0];
|
|
if (!dest) throw new Error('no destination candidate');
|
|
|
|
// Discover the destination's first planet (so it has an objectId).
|
|
const destContent = s.galaxy.contentOf(dest.id);
|
|
const destPlanet = (destContent.planets ?? [])[0];
|
|
const destObjId = destPlanet?.name ?? null;
|
|
|
|
// Set the destination (the route is derived from it).
|
|
s.setDestination(dest.id, destObjId);
|
|
await sleep(400);
|
|
|
|
// Open the MAP console's GALAXY tab (the route + destination ring are
|
|
// drawn there). Use the window's own open() (reveal tween + state).
|
|
s.mapWindow._switchMode('galaxy');
|
|
s.mapWindow.open();
|
|
await sleep(1600); // let the reveal tween + ripple settle + the route paint
|
|
|
|
// Collect the route state for the report.
|
|
const plan = s.routePlan();
|
|
const routeKeys = s.routeEdgeKeys();
|
|
const snap = s.galaxySnapshot();
|
|
const destStar = snap?.systems?.find((x) => x.isDestination);
|
|
const routeEdges = (snap?.edges ?? []).filter((e) => e.route);
|
|
|
|
// --- Now switch to the SYSTEM tab and open the destination system's chart.
|
|
// --- Discover the destination object first (so it's drawn on the chart),
|
|
// --- then the destination ring should appear around it.
|
|
const destSysId = dest.id;
|
|
if (destPlanet) {
|
|
// Discover the destination planet (so it's drawn on the chart).
|
|
let known = s.discovery.bySystem.get(destSysId);
|
|
if (!known) { known = new Set(); s.discovery.bySystem.set(destSysId, known); }
|
|
s.discovery.check(destSysId, destPlanet.x, destPlanet.y, [{ id: destPlanet.name, x: destPlanet.x, y: destPlanet.y, radius: 100 }]);
|
|
}
|
|
await sleep(300);
|
|
|
|
// Switch to the SYSTEM tab and open the destination system's chart.
|
|
s.mapWindow._switchMode('system');
|
|
s.mapWindow._openSystem(destSysId);
|
|
await sleep(1200); // let the chart repaint
|
|
|
|
// Collect the chart state for the report.
|
|
const chartSnap = s.systemChartSnapshotFor(destSysId);
|
|
const destInChart = chartSnap?.objects?.find((o) => o.id === chartSnap.destinationId);
|
|
|
|
window.__ROUTE_SHOT = {
|
|
ready: true,
|
|
errors,
|
|
destSystem: dest.id,
|
|
destName: dest.name,
|
|
destObjId,
|
|
plan: { path: plan?.path, hops: plan?.hops },
|
|
routeKeys,
|
|
destStar: destStar ? { id: destStar.id, name: destStar.name } : null,
|
|
routeEdgeCount: routeEdges.length,
|
|
destinationId: snap?.destinationId,
|
|
chartDestinationId: chartSnap?.destinationId,
|
|
chartDestDiscovered: destInChart?.discovered,
|
|
chartDestName: destInChart?.name,
|
|
};
|
|
|
|
const lines = [
|
|
`DESTINATION: ${dest.name} (${dest.id})`,
|
|
`OBJECT: ${destObjId}`,
|
|
`ROUTE: ${plan?.path?.join(' → ') ?? 'null'}`,
|
|
`HOPS: ${plan?.hops}`,
|
|
`ROUTE EDGES: ${routeEdges.length}`,
|
|
`DEST STAR: ${destStar ? `${destStar.name} (${destStar.id})` : 'null'}`,
|
|
`CHART DEST: ${chartSnap?.destinationId ?? 'null'}`,
|
|
`CHART DEST DISCOVERED: ${destInChart?.discovered}`,
|
|
`CHART DEST NAME: ${destInChart?.name}`,
|
|
`ERRORS: ${errors.length ? errors.join(' | ') : 'none'}`,
|
|
];
|
|
setReport(lines);
|
|
console.log('ROUTE SHOT READY', JSON.stringify(window.__ROUTE_SHOT, null, 2));
|
|
} catch (e) {
|
|
const lines = ['FATAL: ' + (e?.message ?? e), ...errors];
|
|
setReport(lines);
|
|
window.__ROUTE_SHOT = { ready: true, errors: [...errors, String(e?.message ?? e)] };
|
|
}
|