Pause on landing + auto-unpause on dispatch (ISS-041)
CI / build + unit + e2e (pull_request) Successful in 7m43s
CI / build + unit + e2e (pull_request) Successful in 7m43s
Replace the ISS-011 auto-slow with pause-on-landing: when the last plane
in flight lands, tickOnce sets sim_state.paused=true WITHOUT touching
timeScale (speed preserved). flyPlane() now clears paused before
persisting so starting a flight resumes a paused sim — inside runAction(),
tick + unpause + dispatch are atomic under the sim lock.
Tests: engine.test.ts auto-slow block rewritten for pause semantics; new
flyPlane test asserts dispatch clears paused with speed untouched. E2E:
auto-slow.spec.ts renamed to pause-on-landing.spec.ts asserting the new
behavior (paused=true AND timeScale still 1000 after landing; /fly clears
paused). Cross-cutting fix: every per-spec setScale helper now POSTs
{timeScale, paused:false} — a scale-only fast-forward after a landing would
otherwise leave the clock frozen. Deliberate mid-test pauses untouched.
This commit is contained in:
+10
-9
@@ -74,8 +74,8 @@ export async function tickOnce(inst: GameDb): Promise<schema.SimStateRow> {
|
||||
let landedThisTick = 0;
|
||||
if (advanceMs > 0) {
|
||||
await expirePackages(inst, clockMs);
|
||||
// ISS-011: remember the landings so the tick can auto-slow to 1× when this was
|
||||
// the last plane in flight.
|
||||
// ISS-041: remember the landings so the tick can pause when this was the last
|
||||
// plane in flight.
|
||||
landedThisTick = await deliverPackages(inst, clockMs);
|
||||
await spawnOpenPackages(inst, clockMs);
|
||||
// AFTER delivery on purpose: a plane that just landed gets work spawned
|
||||
@@ -83,17 +83,18 @@ export async function tickOnce(inst: GameDb): Promise<schema.SimStateRow> {
|
||||
await spawnCoveragePackages(inst, clockMs);
|
||||
}
|
||||
|
||||
const sets: Partial<Pick<schema.SimStateRow, 'clockMs' | 'lastRealTickMs' | 'timeScale'>> = {
|
||||
const sets: Partial<Pick<schema.SimStateRow, 'clockMs' | 'lastRealTickMs' | 'timeScale' | 'paused'>> = {
|
||||
clockMs,
|
||||
lastRealTickMs: nowMs,
|
||||
};
|
||||
// Auto-slow (ISS-011): when ≥1 plane landed this tick and NO plane remains in flight,
|
||||
// drop the stored timeScale to 1× — persisted here so the UI slider reflects it on the
|
||||
// next snapshot. Arrival-triggered by design: a grounded fleet at high scale is left
|
||||
// alone (the player speeds up manually again; there is no auto-restore).
|
||||
if (landedThisTick > 0 && !sim.paused) {
|
||||
// Pause on landing (ISS-041): when ≥1 plane landed this tick and NO plane remains in flight,
|
||||
// pause the sim WITHOUT touching timeScale — speed is preserved for the next dispatch.
|
||||
// Arrival-triggered by design: a grounded fleet at high scale is left alone (there is no
|
||||
// auto-resume except starting a flight; see flyPlane). A paused tick never processes landings
|
||||
// (advanceMs === 0), so the trigger can only fire on an advancing tick.
|
||||
if (landedThisTick > 0) {
|
||||
const flying = await inst.db.select().from(schema.planes).where(eq(schema.planes.status, 'flying'));
|
||||
if (flying.length === 0) sets.timeScale = MIN_TIME_SCALE;
|
||||
if (flying.length === 0) sets.paused = true;
|
||||
}
|
||||
|
||||
// Persist lastRealTickMs even when nothing advanced — it is the tick anchor.
|
||||
|
||||
Reference in New Issue
Block a user