feat: v0.19.0 — ISS-011 auto-slow to 1x when all planes have landed
CI / build + unit + e2e (pull_request) Successful in 6m14s

This commit is contained in:
2026-09-19 18:07:42 +00:00
parent f0602453ea
commit 86379fc9c6
9 changed files with 261 additions and 7 deletions
+18 -2
View File
@@ -71,17 +71,33 @@ export async function tickOnce(inst: GameDb): Promise<schema.SimStateRow> {
const advanceMs = sim.paused ? 0 : Math.min(elapsed, MAX_TICK_ELAPSED_MS) * sim.timeScale;
const clockMs = Math.round(sim.clockMs + advanceMs);
let landedThisTick = 0;
if (advanceMs > 0) {
await expirePackages(inst, clockMs);
await deliverPackages(inst, clockMs);
// ISS-011: remember the landings so the tick can auto-slow to 1× 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
// at its new location within the same tick.
await spawnCoveragePackages(inst, clockMs);
}
const sets: Partial<Pick<schema.SimStateRow, 'clockMs' | 'lastRealTickMs' | 'timeScale'>> = {
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) {
const flying = await inst.db.select().from(schema.planes).where(eq(schema.planes.status, 'flying'));
if (flying.length === 0) sets.timeScale = MIN_TIME_SCALE;
}
// Persist lastRealTickMs even when nothing advanced — it is the tick anchor.
await inst.db.update(schema.simState).set({ clockMs, lastRealTickMs: nowMs });
await inst.db.update(schema.simState).set(sets);
await persist(inst);
const updated = (await inst.db.select().from(schema.simState))[0];
if (!updated) throw new Error('sim_state row missing after tick');