161 lines
7.0 KiB
GDScript
161 lines
7.0 KiB
GDScript
# 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 字典填充状态。
|
||
# 这个函数无需修改,因为它已经正确处理了包含 "system_status" 的 _state_data。
|
||
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)
|
||
|
||
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 覆盖当前状态。
|
||
# 这个函数无需修改,因为它已经正确处理了包含 "system_status" 的 _state_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))
|
||
|
||
# 获取需要保存到存档的状态。
|
||
# 直接返回核心状态字典的副本。
|
||
# 这个函数无需修改,因为它返回的是完整的 _state_data。
|
||
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:
|
||
# 直接从 _state_data 中读取,通过辅助函数获取字典并访问键值
|
||
# 使用 .get() 并提供默认值 false,增加健壮性
|
||
return _get_system_status_dict().get("game_pause", false)
|
||
|
||
# 检查是否处于任务中状态
|
||
# 返回: bool - true 如果正在进行任务, false 否则
|
||
func is_on_task_status() -> bool:
|
||
# 直接从 _state_data 中读取
|
||
# 使用 .get() 并提供默认值 false,增加健壮性
|
||
return _get_system_status_dict().get("is_on_task", false)
|
||
|
||
# 暂停游戏
|
||
func pause_game():
|
||
# 调用新的辅助函数来修改 _state_data 中的 "game_pause" 值
|
||
set_system_status_value("game_pause", true)
|
||
|
||
# 恢复游戏
|
||
func resume_game():
|
||
# 调用新的辅助函数来修改 _state_data 中的 "game_pause" 值
|
||
set_system_status_value("game_pause", false)
|