replace polling timers with sorted event queues + action log

Crops, tree seedlings, and tile recovery no longer iterate all entries
every frame. Each event stores an absolute gameTime timestamp (growsAt).
A sorted priority queue is drained each tick — only due items are touched.

WorldState now tracks gameTime (ms); stateManager.advanceTime(delta)
increments it each frame. Save version bumped 5→6 with migration.

Action log ring buffer (15 entries) added to LocalAdapter; shown in
the F3 debug panel under "Last Actions".

Closes #36
Closes #37
This commit is contained in:
2026-03-24 08:08:05 +00:00
parent d02ed33435
commit 3b021127a4
8 changed files with 279 additions and 81 deletions

View File

@@ -38,7 +38,8 @@ export class TreeSeedlingSystem {
* @param delta - Frame delta in milliseconds
*/
update(delta: number): void {
const advanced = stateManager.tickSeedlings(delta)
// Drain seedling growth queue (no delta — gameTime is advanced by GameScene)
const advanced = stateManager.tickSeedlings()
for (const id of advanced) {
const state = stateManager.getState()
const seedling = state.world.treeSeedlings[id]
@@ -91,7 +92,7 @@ export class TreeSeedlingSystem {
const seedling: TreeSeedlingState = {
id, tileX, tileY,
stage: 0,
stageTimerMs: TREE_SEEDLING_STAGE_MS,
growsAt: stateManager.getGameTime() + TREE_SEEDLING_STAGE_MS,
underlyingTile,
}