diff --git a/src/main.ts b/src/main.ts index 8107dc0..9e6c188 100644 --- a/src/main.ts +++ b/src/main.ts @@ -53,11 +53,20 @@ const game = new Phaser.Game({ const ROUTES = { night: 'Night', parade: 'Parade', floor: 'FloorDemo', juice: 'JuiceDemo' } as const; type RouteKey = keyof typeof ROUTES; +// Only ROOT scenes are routed. Door, Floor and NightSummary belong to Night and +// go down with its teardown; stopping them from here used to leave a live Night +// driving a dead Door — a black screen with no way back, because the guard +// below then declined to restart the already-active Night. +const ROOT_SCENES = ['Roster', 'Night', 'Parade', 'FloorDemo', 'JuiceDemo'] as const; + const showScene = (target: (typeof ROUTES)[RouteKey]): void => { - for (const key of ['Roster', 'Night', 'Door', 'NightSummary', 'Parade', 'FloorDemo', 'JuiceDemo']) { + for (const key of ROOT_SCENES) { if (key !== target && game.scene.isActive(key)) game.scene.stop(key); } - if (!game.scene.isActive(target)) game.scene.start(target); + // Pressing a route key for what is already running means "start it over". + // It is the only way to get a fresh night out of N mid-shift. + if (game.scene.isActive(target)) game.scene.stop(target); + game.scene.start(target); }; // RosterScene is scene[0] and auto-starts. Hash routing must wait until it is diff --git a/src/scenes/door/NightScene.ts b/src/scenes/door/NightScene.ts index aa4fdea..4726c25 100644 --- a/src/scenes/door/NightScene.ts +++ b/src/scenes/door/NightScene.ts @@ -573,6 +573,12 @@ export class NightScene extends Phaser.Scene { } private teardown(): void { + // Door and Floor are this scene's children — they hold this night's bus, + // clock and context. A Night that goes away without taking them leaves two + // scenes driving a dead bus, and a restarted Night would launch a second + // pair on top of the first. + this.scene.stop('Door'); + this.scene.stop('Floor'); for (const off of this.offs) off(); this.offs = []; this.meters?.destroy();