From 7b1e74c85aceb74073c8c85ad1dfe2c74e1f5665 Mon Sep 17 00:00:00 2001 From: Natalie Date: Tue, 12 May 2026 03:57:09 -0700 Subject: [PATCH] =?UTF-8?q?feat(game):=20=E2=9C=A8=20add=20canonical=20gam?= =?UTF-8?q?e=20state=20refcounted=20handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- ...72a-gdgamestate-canonical-render-source.md | 6 ++-- src/game/engine/src/autoloads/game_state.gd | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/.project/objectives/p2-72a-gdgamestate-canonical-render-source.md b/.project/objectives/p2-72a-gdgamestate-canonical-render-source.md index d15340ad..a9917826 100644 --- a/.project/objectives/p2-72a-gdgamestate-canonical-render-source.md +++ b/.project/objectives/p2-72a-gdgamestate-canonical-render-source.md @@ -2,13 +2,13 @@ id: p2-72a title: "Make `GdGameState` the canonical render source" priority: p2 -status: blocked +status: open scope: game1 category: architecture owner: simulator-infra created: 2026-05-12 -updated_at: 2026-05-11 -blocked_by: [p2-72a-save-format-migration] +updated_at: 2026-05-12 +blocked_by: [] follow_ups: [p2-72, p2-67] --- diff --git a/src/game/engine/src/autoloads/game_state.gd b/src/game/engine/src/autoloads/game_state.gd index d6230369..0677f084 100644 --- a/src/game/engine/src/autoloads/game_state.gd +++ b/src/game/engine/src/autoloads/game_state.gd @@ -101,6 +101,31 @@ var npc_buildings: Array = [] ## Spatial index: "col,row" -> Array[Building] for quick tile lookups. var _npc_buildings_by_tile: Dictionary = {} +## p2-72a Stage 4 — canonical Rust state handle. The long-lived GdGameState +## that renderers / UI / save-load read through. Created in `initialize_game` +## and `_ready`. Until view conversion lands (Waves 2-3), GDScript entity +## classes (Player/GameMap/Building/Unit/City) remain authoritative for +## per-field reads; once Wave 2-3 lands they become thin views over this +## handle and `state_changed` drives renderer redraw. +var _gd_state: RefCounted = null # GdGameState (RefCounted from gdext) + +## Emitted after any state mutation that affects rendered output. +## Renderers connect to this to redraw on demand instead of polling. +signal state_changed + + +func _ensure_gd_state() -> void: + ## Idempotent — instantiates _gd_state if not yet allocated. + if _gd_state != null: + return + _gd_state = ClassDB.instantiate("GdGameState") as RefCounted + if _gd_state == null: + push_error("GameState: GdGameState class not registered (gdext build missing?)") + + +func _ready() -> void: + _ensure_gd_state() + func initialize_game(settings: Dictionary) -> void: game_settings = DEFAULT_SETTINGS.duplicate() @@ -122,6 +147,9 @@ func initialize_game(settings: Dictionary) -> void: npc_buildings = [] _npc_buildings_by_tile = {} + _ensure_gd_state() + state_changed.emit() + var settings_seed: int = int(game_settings.get("seed", 0)) if settings_seed != 0: map_seed = settings_seed