# GameState.gd # Autoload Singleton # 负责存储和管理核心游戏状态。 # 使用一个中央字典 (_state_data) 来存储所有状态,提高灵活性和可维护性。 # 状态的键名直接来源于初始化数据 (Init_Base.json) 或后续动态添加。 extends Node # --- 状态信号 --- # 当游戏状态通过 initialize_for_new_game 初始化完成时发出 signal state_initialized(initial_state: Dictionary) # 当游戏状态通过 restore_state 从存档恢复完成时发出 signal state_restored(restored_state: Dictionary) # 当任何状态值通过 set_value 发生改变时发出 signal state_value_changed(key: String, new_value) # [兼容性信号] 当 "time" 状态值被设置或更新时发出 (保持与旧代码或特定UI的兼容) signal date_changed(new_date: Dictionary) # --- 内部状态变量 --- # 核心状态字典,存储所有动态游戏数据 var _state_data: Dictionary = {} # 注意:内部的 game_pause 和 is_on_task 变量已被移除, # 相关状态现在存储在 _state_data["system_status"] 中。 # --- 状态初始化与恢复 --- # 为新游戏初始化状态。 # 直接使用传入的 initial_settings 字典填充状态。 func initialize_for_new_game(initial_settings: Dictionary) -> void: print("GameState: Initializing state directly from initial settings...") # 使用深拷贝 (duplicate(true)),确保 GameState 拥有独立的数据副本 _state_data = initial_settings.duplicate(true) # 在 _state_data 初始化后,调用 add_init_data 来填充 "task_info" add_init_data() # 调用修改后的函数 print("GameState: State initialized. Data:", _state_data) # 发出通用初始化完成信号,传递状态副本 emit_signal("state_initialized", _state_data.duplicate(true)) # [兼容性] 如果存在 "time" 键,则发出 date_changed 信号 if _state_data.has("time") and typeof(_state_data["time"]) == TYPE_DICTIONARY: emit_signal("date_changed", _state_data["time"].duplicate(true)) # 从加载的数据恢复状态。 # 直接使用 loaded_data 覆盖当前状态。 func restore_state(loaded_data: Dictionary) -> void: print("GameState: Restoring state from loaded data...") # 同样建议使用深拷贝,虽然从存档加载的数据理论上已经是独立的 _state_data = loaded_data.duplicate(true) print("GameState: State restored. Data:", _state_data) # 发出通用恢复完成信号,传递状态副本 emit_signal("state_restored", _state_data.duplicate(true)) # [兼容性] 如果存在 "time" 键,则发出 date_changed 信号 if _state_data.has("time") and typeof(_state_data["time"]) == TYPE_DICTIONARY: emit_signal("date_changed", _state_data["time"].duplicate(true)) # 获取需要保存到存档的状态。 # 直接返回核心状态字典的副本。 func get_savable_state() -> Dictionary: print("GameState: Gathering savable state...") # 返回深拷贝,确保存档系统拿到的是快照,不会意外修改当前状态 return _state_data.duplicate(true) # --- 状态访问 (通用 Getter) --- # 获取指定键 (key) 的状态值。 # 如果键不存在,返回提供的默认值 (default)。 func get_value(key: String, default = null): # 使用字典的 get 方法,它能优雅地处理键不存在的情况 return _state_data.get(key, default) # --- 状态修改 (通用 Setter) --- # 设置指定键 (key) 的状态值。 # 如果值发生变化,会发出 state_value_changed 信号。 # 如果键是 "time",还会额外发出 date_changed 信号。 func set_value(key: String, value) -> void: var old_value = _state_data.get(key) # 只有当值确实发生改变时才执行更新和发信号,提高效率 # 注意:对于字典或数组等引用类型,这个比较是浅比较。 if old_value != value: _state_data[key] = value #print("GameState: Value changed - ", key, ": ", value) # 发出通用值变化信号 emit_signal("state_value_changed", key, value) # [兼容性] 如果更新的是 "time" 键,且值是字典,则发出 date_changed 信号 if key == "time" and typeof(value) == TYPE_DICTIONARY: emit_signal("date_changed", value.duplicate(true)) # 发送新日期的副本 # --- 系统状态访问辅助函数 (新添加) --- # 内部辅助函数:安全地获取 "system_status" 字典 # 返回一个字典的副本,如果原始数据无效或不存在,则返回包含默认值的字典 func _get_system_status_dict() -> Dictionary: var status = get_value("system_status") # 验证获取到的值是否为字典,如果不是或为 null,则返回默认结构 if typeof(status) != TYPE_DICTIONARY: printerr("GameState: 'system_status' key missing or not a Dictionary in _state_data. Returning default.") return {"game_pause": false, "is_on_task": false} # 返回深拷贝以防止外部意外修改原始字典的引用(虽然 get_value 返回的通常是副本或基础类型) return status.duplicate(true) # 设置 "system_status" 中的特定键值 (game_pause 或 is_on_task) # key: 要设置的键名 ("game_pause" 或 "is_on_task") # value: 要设置的布尔值 (true 或 false) func set_system_status_value(key: String, value: bool) -> void: # 获取当前的 system_status 字典的副本 var current_status = _get_system_status_dict() # 检查键是否是预期的 "game_pause" 或 "is_on_task" if key == "game_pause" or key == "is_on_task": # 只有当值实际改变时才更新,以避免不必要的 set_value 调用和信号发射 if current_status.get(key) != value: current_status[key] = value # 使用通用的 set_value 来更新整个 system_status 字典 # 这将触发 state_value_changed("system_status", new_dictionary) 信号 set_value("system_status", current_status) print("GameState: Updated system_status -> ", key, " set to ", value) # else: # 值未改变,无需操作 # print("GameState: system_status -> ", key, " already set to ", value) else: printerr("GameState: Invalid key '", key, "' provided to set_system_status_value. Expected 'game_pause' or 'is_on_task'.") # 检查游戏是否暂停 # 返回: bool - true 如果游戏已暂停, false 否则 func is_game_paused() -> bool: return _get_system_status_dict().get("game_pause", false) # 检查是否处于任务中状态 # 返回: bool - true 如果正在进行任务, false 否则 func is_on_task_status() -> bool: return _get_system_status_dict().get("is_on_task", false) # 暂停游戏 func pause_game(): set_system_status_value("game_pause", true) # 恢复游戏 func resume_game(): set_system_status_value("game_pause", false) # --- 辅助函数:查找字典中第一个 enabled:true 的条目的键 --- # data_dict: 期望是一个结构为 { "key1": {"enabled": bool, ...}, "key2": {...} } 的字典 # 返回: 第一个找到的 enabled 为 true 的条目的键名 (String),如果未找到则返回空字符串 func _find_first_enabled_key(data_dict: Dictionary) -> String: if typeof(data_dict) != TYPE_DICTIONARY: printerr("GameState (_find_first_enabled_key): Expected a Dictionary, got ", typeof(data_dict)) return "" # GDScript 字典从 Godot 3.1 开始保持插入顺序, # 因此迭代将遵循 JSON 中定义的顺序或它们被添加到字典中的顺序。 for key in data_dict: var item = data_dict[key] if typeof(item) == TYPE_DICTIONARY and item.has("enabled") and item["enabled"] == true: return key # 返回第一个找到的键名 # print("GameState (_find_first_enabled_key): No enabled item found in dictionary with keys: ", data_dict.keys()) # 可选的调试信息 return "" # 如果没有找到 enabled:true 的条目 # --- 初始化 task_info --- # MODIFIED: 此函数现在会从 _state_data["task_development"] 获取初始值 func add_init_data() -> void: var initial_platform: String = "" var initial_gameplay: String = "" var initial_theme: String = "" var initial_strategy: String = "" var initial_product_focus_points: Dictionary = {} # 确保 _state_data["task_development"] 存在并且是字典类型 if _state_data.has("task_development") and typeof(_state_data["task_development"]) == TYPE_DICTIONARY: var task_dev_data = _state_data["task_development"] # 获取平台初始值 if task_dev_data.has("platforms") and typeof(task_dev_data["platforms"]) == TYPE_DICTIONARY: initial_platform = _find_first_enabled_key(task_dev_data["platforms"]) else: printerr("GameState (add_init_data): 'task_development.platforms' is missing or not a Dictionary.") # 获取玩法初始值 if task_dev_data.has("gameplays") and typeof(task_dev_data["gameplays"]) == TYPE_DICTIONARY: initial_gameplay = _find_first_enabled_key(task_dev_data["gameplays"]) else: printerr("GameState (add_init_data): 'task_development.gameplays' is missing or not a Dictionary.") # 获取题材初始值 if task_dev_data.has("themes") and typeof(task_dev_data["themes"]) == TYPE_DICTIONARY: initial_theme = _find_first_enabled_key(task_dev_data["themes"]) else: printerr("GameState (add_init_data): 'task_development.themes' is missing or not a Dictionary.") # 获取开发策略初始值 if task_dev_data.has("strategies") and typeof(task_dev_data["strategies"]) == TYPE_DICTIONARY: initial_strategy = _find_first_enabled_key(task_dev_data["strategies"]) else: printerr("GameState (add_init_data): 'task_development.strategies' is missing or not a Dictionary.") # 获取产品侧重点初始值 if task_dev_data.has("product_focus_points") and typeof(task_dev_data["product_focus_points"]) == TYPE_DICTIONARY: initial_product_focus_points = task_dev_data["product_focus_points"] else: printerr("GameState (add_init_data): 'task_development.product_focus_points' is missing or not a Dictionary.") else: printerr("GameState (add_init_data): 'task_development' key is missing in _state_data or is not a Dictionary.") # 初始化 _state_data["task_info"] _state_data["task_info"] = { "平台": initial_platform, "玩法": initial_gameplay, "题材": initial_theme, "开发策略": initial_strategy, "预算": 0, # 保持原有的默认值 "产品侧重点": initial_product_focus_points, #"关键环节负责人": [] # 保持原有的默认值 }