diff --git a/client/scripts/autoloads/game_state.gd b/client/scripts/autoloads/game_state.gd index 8294f030b..d96294fd2 100644 --- a/client/scripts/autoloads/game_state.gd +++ b/client/scripts/autoloads/game_state.gd @@ -1,5 +1,7 @@ extends Node +signal game_id_changed(new_id: String) + # Updated each frame from ObserverSnapshot data (Protocol format: {tick, entities, tiles}). # Entities use Protocol decoded format: {entity_id, x, y, z, kind: {variant, data}}. # Tiles use format: [{x, y, z, type}]. @@ -8,7 +10,10 @@ var current_snapshot: Dictionary = {} # D-085 (#258): Active game session identifier. Format: -- # Set by SessionManager.new_game() or SessionManager.resume_game(). # Empty string when no session is active (main menu state). -var current_game_id: String = "" +var current_game_id: String = "": + set(v): + current_game_id = v + game_id_changed.emit(v) var current_tick: int = 0 var player_position: Vector2 = Vector2.ZERO var visible_entities: Array = [] diff --git a/client/scripts/autoloads/session_manager.gd b/client/scripts/autoloads/session_manager.gd index a41c4b554..da1ddade7 100644 --- a/client/scripts/autoloads/session_manager.gd +++ b/client/scripts/autoloads/session_manager.gd @@ -22,7 +22,6 @@ func new_game() -> String: now.hour, now.minute, now.second, ] var rng := RandomNumberGenerator.new() - rng.randomize() var hex_seed := "%06x" % (rng.randi() & 0xFFFFFF) var game_id := "%s-%s" % [timestamp, hex_seed] var save_path := SAVES_DIR + game_id + "/" @@ -69,16 +68,15 @@ func list_game_dirs() -> Array: ## Show "Save before quitting?" confirmation dialog, then return to main menu. -## node: the calling scene node (used as dialog parent). ## #554: The actual F5 save will be wired here once server supports SaveCommand. -func quit_to_menu(node: Node) -> void: +func quit_to_menu() -> void: if _quit_dialog != null and is_instance_valid(_quit_dialog): return # Dialog already open _quit_dialog = ConfirmationDialog.new() _quit_dialog.dialog_text = UIStrings.get_text("menu.confirm_quit") _quit_dialog.ok_button_text = UIStrings.get_text("menu.confirm_yes") _quit_dialog.cancel_button_text = UIStrings.get_text("menu.confirm_no") - node.add_child(_quit_dialog) + get_tree().root.add_child(_quit_dialog) _quit_dialog.confirmed.connect(_do_quit_to_menu) _quit_dialog.canceled.connect(_cleanup_quit_dialog) _quit_dialog.popup_centered() diff --git a/client/scripts/autoloads/sim_bridge.gd b/client/scripts/autoloads/sim_bridge.gd index f1d4f7fd0..5e7b52283 100644 --- a/client/scripts/autoloads/sim_bridge.gd +++ b/client/scripts/autoloads/sim_bridge.gd @@ -72,6 +72,9 @@ var _test_npc_relationship: String: set(v): if harness: harness.npc_relationship = v +var _test_input_queue: Array: + get: return harness.input_queue if harness else [] + # -- Connection lifecycle ------------------------------------------------------ diff --git a/client/scripts/ui/debug_overlay.gd b/client/scripts/ui/debug_overlay.gd index 041f92b0a..362e5758d 100644 --- a/client/scripts/ui/debug_overlay.gd +++ b/client/scripts/ui/debug_overlay.gd @@ -77,6 +77,15 @@ func _ready() -> void: _dev_mode = OS.is_debug_build() visible = false _cached_font = ThemeDB.fallback_font + # Clear NPC path history on session change to prevent entity ID collisions + GameState.connect("game_id_changed", _on_game_id_changed) + + +func _on_game_id_changed(_new_id: String) -> void: + _npc_paths.clear() + _tick_deltas.clear() + _tick_times.clear() + _last_tick_processed = -1 func _unhandled_input(event: InputEvent) -> void: diff --git a/client/ui/settings_dialog.gd b/client/ui/settings_dialog.gd index 55ed74591..cbde721e3 100644 --- a/client/ui/settings_dialog.gd +++ b/client/ui/settings_dialog.gd @@ -163,7 +163,7 @@ func _draw() -> void: func _on_quit_to_menu() -> void: close() - SessionManager.quit_to_menu(get_tree().root) + SessionManager.quit_to_menu() static func _format_db(db: float) -> String: