/** * Dev-only: boot GameScene, set a DESTINATION (a far star), and open the * MAP console's CURRENT SYSTEM tab so a headless screenshot shows: * · the ROUTE EXIT GATE circled in orange (the gate the player should * path out of the system from to reach the destination), * · an orange line from the ship to that gate ("path out of the system"). * * node dev/server.mjs 8084 * node dev/shot-firefox.mjs \ * "http://127.0.0.1:8084/dev/exit-gate-shot.html" \ * "window.__EXIT_GATE ? window.__EXIT_GATE.ready : null" \ * EXIT_GATE.png 40000 * * The report (top-left) lists console errors + the exit-gate 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); 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; 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); // Pick a FAR destination (a multi-hop route, so the exit gate is the // route's next gate in the CURRENT system). 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; }); const dest = others[2] ?? others[0]; if (!dest) throw new Error('no destination candidate'); const destContent = s.galaxy.contentOf(dest.id); const destPlanet = (destContent.planets ?? [])[0]; const destObjId = destPlanet?.name ?? null; // Set the destination. s.setDestination(dest.id, destObjId); await sleep(400); // Discover the exit gate (the route's next gate in the CURRENT system) // so it's drawn on the chart. const exitGate = s.routeNextGate(); if (exitGate) { let known = s.discovery.bySystem.get(sysId); if (!known) { known = new Set(); s.discovery.bySystem.set(sysId, known); } s.discovery.check(sysId, exitGate.x, exitGate.y, [{ id: exitGate.discoveryId, x: exitGate.x, y: exitGate.y, radius: 100 }]); } await sleep(300); // Open the MAP console's CURRENT SYSTEM tab (the default mode). s.mapWindow._switchMode('currentSystem'); s.mapWindow.open(); await sleep(1600); // Collect the state for the report. const chartSnap = s.mapChartSnapshot(); const exitInfo = chartSnap?.routeExitGate; const exitObj = (chartSnap?.objects ?? []).find((o) => o?.id === exitInfo?.id); window.__EXIT_GATE = { ready: true, errors, destSystem: dest.id, destName: dest.name, exitGateId: exitInfo?.id, exitGateName: exitInfo?.name, exitGateDiscovered: exitObj?.discovered, exitGateX: exitInfo?.x, exitGateY: exitInfo?.y, shipX: chartSnap?.ship?.x, shipY: chartSnap?.ship?.y, destinationId: chartSnap?.destinationId, }; const lines = [ `DESTINATION: ${dest.name} (${dest.id})`, `EXIT GATE: ${exitInfo?.name ?? 'null'} (${exitInfo?.id ?? 'null'})`, `EXIT GATE DISCOVERED: ${exitObj?.discovered}`, `EXIT GATE POS: (${exitInfo?.x?.toFixed(0)}, ${exitInfo?.y?.toFixed(0)})`, `SHIP POS: (${chartSnap?.ship?.x?.toFixed(0)}, ${chartSnap?.ship?.y?.toFixed(0)})`, `DESTINATION IN CURRENT SYS: ${chartSnap?.destinationId ?? 'no (route exit gate shown)'}`, `ERRORS: ${errors.length ? errors.join(' | ') : 'none'}`, ]; setReport(lines); console.log('EXIT GATE READY', JSON.stringify(window.__EXIT_GATE, null, 2)); } catch (e) { const lines = ['FATAL: ' + (e?.message ?? e), ...errors]; setReport(lines); window.__EXIT_GATE = { ready: true, errors: [...errors, String(e?.message ?? e)] }; }