From d4a9d91c5d82ecb626cdc9d2b708625d31fa293e Mon Sep 17 00:00:00 2001 From: Malte Langkabel Date: Sun, 19 Jul 2026 20:25:01 +0200 Subject: [PATCH] document the pull-on-demand convention for reading simulation state in the UI UI widgets hold the Simulation and read authoritative values via getters on demand; state-change events are refresh signals, not carriers of truth. This codifies the pattern used by BuildButtonGrid and avoids stale-cache bugs. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Y7N59FsLA5e2kuVdqe4Uhc --- docs/architecture.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/architecture.md b/docs/architecture.md index fef47f9..655b949 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -97,6 +97,12 @@ All UI interactions — building selection, builder/blueprint mode transitions, Bidirectional interactions use separate request/notification event types to avoid infinite recursion (e.g., `ExitBuilderModeRequestedEvent` from `BuildButtonGrid` → `GameWorldView`, vs. `BuilderModeExitedEvent` from `GameWorldView` → `BuildButtonGrid`). +### Reading Simulation State + +The simulation is the single source of truth for every game value (building block stock, expansion cost, threat level, tick, etc.). A UI widget that needs such a value holds the `Simulation*` it was constructed with and **pulls the value on demand** via the corresponding getter (e.g., `m_sim->getBuildingBlocksStock()`), rather than caching its own copy. + +State-change events (e.g., `BuildingBlocksChangedEvent`) are treated as *refresh signals*, not as carriers of truth: a widget subscribes to the event to learn *when* the value changed and then re-reads it from the simulation to learn *what* it now is. The value carried in the event payload is not authoritative and should not be stored. This keeps a single copy of each value and avoids stale-cache bugs (a widget acting on a value that has since moved on because nothing refreshed its local copy). + ## Tick Order Within a single simulation tick, subsystems run in this fixed order. The order is load-bearing for determinism and for avoiding one-tick-delay artifacts (e.g., items landing on a belt but not advancing in the same tick).