17 KiB
17 KiB
核心 Autoload 管理器说明文档 (v1.4 - 基于代码审查)
文档目的: 本文档旨在详细说明游戏核心的四个 Autoload 管理器 (InitializationManager, InitialDataManager, GameState, SaveLoadManager) 的设计、职责、交互方式以及对外提供的接口(API)。特别注意:本文档描述的是基于“数据枢纽”模型的架构,并已根据最新代码实现进行更新。 它是后续开发其他游戏玩法模块(如员工管理、项目管理、UI 等)时的主要参考依据,确保各模块能正确、高效地与核心系统协作。
重要:模块开发者的责任 (Module Developer Responsibilities)
在当前的“数据枢纽”模型下,GameState 仅作为通用数据容器。因此,各个功能模块(如员工管理、项目管理、UI 等)承担以下关键责任:
- Key 管理: 定义并维护模块自身所需状态数据在
GameState中的唯一key。建议采用命名空间或前缀避免冲突 (e.g.,"employee.list","project.active_ids")。 - 数据结构定义: 定义与模块相关的
key所对应的value的具体数据结构(字典、数组、基础类型等)。 - 初始化/状态恢复:
- 必须监听
GameState的state_restored信号。 - 在该信号的回调函数中,调用
GameState.get_value(key)来获取本模块所需的所有数据。 - 使用获取到的数据完成模块自身的初始化或状态恢复(更新内部变量、刷新 UI 等)。
- 必须监听
- 数据读取与更新: 通过
GameState.get_value(key)读取状态,通过GameState.set_value(key, new_value)更新状态。 - 业务逻辑验证: 所有业务逻辑相关的验证(如花钱前检查余额、操作是否允许等)必须在调用
GameState.set_value之前由模块自身完成。GameState不进行任何业务逻辑校验。 - 数据序列化: 确保存入
GameState的所有数据都是可被 Godot 的 JSON 模块序列化的(避免存入 Node 引用等)。
1. 初始化管理器 (InitializationManager)
目标 (Purpose/Goal)
- 作为游戏启动流程的总控制器,统一协调新游戏开始或存档加载的准备工作。
- 确保在通知模块进行状态恢复前,
GameState已被正确的数据填充。 - 提供一个清晰的入口点来响应用户的启动选择(新游戏/加载)。
核心职责 (Responsibilities)
- 流程决策: 根据用户输入(来自主菜单 UI),决定启动“新游戏”流程还是“载入存档”流程。
- 数据准备:
- 新游戏: 确保
InitialDataManager数据加载完成 -> 调用InitialDataManager获取初始数据 (settings_data,task_dev_data,npc_initial_data) -> 调用_build_initial_state方法,根据获取的数据构建注入GameState的初始状态字典。此方法会:- 合并基础设置 (
Init_Base.json) 到状态字典的顶层。 - 处理任务开发相关数据 (
task_development.json),提取其中需要动态追踪的状态(如平台的enabled,Market_share;玩法/主题的enabled,Experience;策略的enabled;产品侧重点的完整结构),并将这些动态状态组织在一个名为"task_development"的子字典内,再将该子字典存入主状态字典。 - 处理 NPC 数据 (
npc.json),将从npc_initial_data中获取的 NPC 定义(通常是npc_defs["npc"]部分,即npc.json文件中 "npc" 键对应的值)存入主状态字典的"npcs"键下。
- 合并基础设置 (
- 载入存档: 接收由外部(例如存档选择 UI,它会调用
SaveLoadManager.load_game)加载并传入的存档数据字典。
- 新游戏: 确保
- 数据注入:
- 新游戏: 将构建好的初始状态字典传递给
GameState.initialize_for_new_game()。 - 载入存档: 将接收到的存档数据字典传递给
GameState.restore_state()。
- 新游戏: 将构建好的初始状态字典传递给
- 流程控制: 管理初始化过程中的用户反馈(如显示/隐藏加载界面),并在
GameState准备就绪后(通过信号通知),触发到主游戏场景的切换(此部分逻辑通常在此管理器或调用它的 UI 中实现)。 - 错误处理: 捕获并处理在初始化过程中(如
InitialDataManager加载失败、构建初始状态失败)发生的错误,向用户提供反馈并阻止进入游戏。
对外接口 (Public API)
start_new_game_process() -> bool: 由主菜单调用,启动新游戏流程。成功返回true,失败返回false。load_game_process(save_data: Dictionary) -> bool: 接收已加载的存档数据字典save_data,启动加载流程。成功返回true,失败返回false。(注意: 此函数不负责从文件加载数据,它期望save_data已经被加载好并传入)。- 注意: 其他游戏玩法模块通常不需要在游戏运行过程中直接调用此管理器。其主要交互对象是启动阶段的 UI。
对外信号 (Public Signals)
new_game_initialized: 在start_new_game_process成功执行,GameState被初始化后发出。game_loaded: 在load_game_process成功执行,GameState被恢复后发出。
交互关键点 (Key Interactions)
- 接收: 来自 UI 的调用 (
start_new_game_process,load_game_process)。 - 调用:
InitialDataManager(在新游戏流程中调用ensure_data_loaded,get_starting_settings,get_task_development_data,get_npc_initial_data),GameState(调用initialize_for_new_game或restore_state)。 - 发出:
new_game_initialized,game_loaded信号。 - (可能)
SceneTree(用于切换场景,虽然未在提供的代码片段中直接显示,但通常是其职责一部分)。
核心逻辑流程 (Core Logic/Flow)
- 新游戏: (UI 调用
start_new_game_process) -> 显示加载 -> 确保InitialDataManager就绪 -> 获取初始数据 (settings,task_dev,npc_initial_data) -> 调用_build_initial_state构建包含"task_development"和"npcs"结构的初始状态字典 -> 调用GameState.initialize_for_new_game()-> 发出new_game_initialized信号 -> (后续逻辑) 切换场景 -> 隐藏加载。 - 载入存档: (UI 调用
SaveLoadManager.load_game(slot_id)得到save_data字典) -> (UI 调用load_game_process(save_data)) -> 显示加载 -> (可选:确保InitialDataManager就绪) -> 调用GameState.restore_state(save_data)-> 发出game_loaded信号 -> (后续逻辑) 切换场景 -> 隐藏加载。 - 在每个关键步骤后检查成功/失败状态,失败则中止流程并反馈用户。
配置 (Configuration)
- 必须配置为 Godot 的 Autoload (单例),以便全局访问。
2. 初始化数据管理器 (InitialDataManager)
目标 (Purpose/Goal)
- 负责加载和管理游戏的基础静态配置数据。
- 提供对这些数据的只读访问接口。
- 作为新游戏流程中构建初始状态字典的数据来源之一。
- 实现数据与游戏逻辑代码的分离。
核心职责 (Responsibilities)
- 数据读取与解析: 从
res://Data/下的.json文件加载数据 (当前加载Init_Base.json,task_development.json, 和npc.json)。 - 数据存储与缓存: 内部存储解析后的数据,确保只加载一次。
- 数据提供: 通过函数接口提供数据的深拷贝副本。
对外接口 (Public API / Data Access Functions)
ensure_data_loaded() -> bool: 确保所有必需的初始数据 (Init_Base.json,task_development.json,npc.json) 已加载。通常由InitializationManager在新游戏流程开始时调用。返回加载是否成功。get_starting_settings() -> Dictionary: 获取Init_Base.json中的初始游戏设定。返回数据的深拷贝。get_task_development_data() -> Dictionary: 获取task_development.json中的所有数据。返回数据的深拷贝。get_npc_initial_data() -> Dictionary: 获取npc.json中的所有数据。返回数据的深拷贝。- 数据规范: 返回的数据结构遵循 JSON 文件结构。所有通过此管理器获取的数据都应视为只读。
对外信号 (Public Signals)
- 通常不发出信号,因为它主要提供静态数据查询。
交互关键点 (Key Interactions)
- 被调用:
InitializationManager(用于构建初始状态字典), 以及任何需要在运行时查询基础静态配置的模块(如 UI 显示、逻辑判断等)。
数据处理 (Data Handled)
- 输入:
res://Data/路径下的Init_Base.json,task_development.json,npc.json文件。 - 输出: 解析后的 Godot 数据结构(字典),通过函数接口提供(作为深拷贝副本)。
配置 (Configuration)
- 必须配置为 Godot 的 Autoload (单例)。
3. 游戏状态管理器 (GameState)
目标 (Purpose/Goal)
- 作为游戏运行时动态状态的中央存储库 (Data Hub)。
- 提供通用的 Key-Value 接口供其他系统存储和检索游戏状态数据。
- 不理解存储数据的具体含义或结构。
- 在状态数据被完全初始化或恢复后,通知所有监听模块。
- 管理游戏暂停状态及其他系统级状态(如是否在任务中),这些状态统一存储在
_state_data的"system_status"键下的字典中。
核心职责 (Responsibilities)
- 状态存储: 内部维护一个核心字典 (
_state_data),用于存储所有动态游戏状态的 Key-Value 对。 - 通用状态访问: 提供通用的
set_value,get_value接口。 - 状态初始化: 提供
initialize_for_new_game方法,使用初始设置数据填充状态字典,并在此过程中调用内部方法(如add_init_data)根据已填充的_state_data的一部分(例如"task_development")来进一步初始化其他状态数据(例如"task_info"), 完成后发出state_initialized信号。 - 状态恢复与通知: 提供
restore_state方法用于接收并覆盖整个状态字典,完成后发出state_restored信号。 - 存档数据提供: 提供
get_savable_state方法,返回内部状态字典的深拷贝副本,供SaveLoadManager使用。 - 系统状态管理: 通过内部的
"system_status"字典(存储在_state_data["system_status"])管理如游戏暂停 (game_pause)、是否在任务中 (is_on_task) 等状态。提供方法来修改和查询这些特定状态。
对外接口 (Public API / Generic State Access)
initialize_for_new_game(initial_settings: Dictionary) -> void: (供 InitializationManager 调用) 使用initial_settings字典(进行深拷贝)来初始化内部的_state_data。随后,会调用一个内部函数 (add_init_data),该函数读取_state_data中已存在的"task_development"数据,并用其来填充_state_data中的"task_info"键。 完成后发出state_initialized信号。restore_state(loaded_data: Dictionary) -> void: (供 InitializationManager 调用) 用loaded_data字典(进行深拷贝)完全替换内部的_state_data字典,然后发出state_restored信号。get_savable_state() -> Dictionary: (供 SaveLoadManager 调用) 返回内部_state_data字典的深拷贝 (duplicate(true)),用于存档,确保返回的是当前状态的一个独立快照。get_value(key: String, default = null) -> Variant: 根据key从内部字典检索value。如果key不存在,返回default值。set_value(key: String, value: Variant) -> void: 向内部字典设置或更新一个 Key-Value 对。注意:调用者负责确保value是可序列化的,并进行必要的业务逻辑验证。 只有当新值与旧值通过!=(浅比较) 判断为不同时,才会实际更新并发出state_value_changed信号。如果key是"time"且value是字典,还会额外发出date_changed兼容性信号。pause_game() -> void: 通过set_system_status_value("game_pause", true)修改状态,将"system_status"中的game_pause设置为true。resume_game() -> void: 通过set_system_status_value("game_pause", false)修改状态,将"system_status"中的game_pause设置为false。set_system_status_value(key: String, value: bool) -> void: 设置"system_status"字典中指定key("game_pause"或"is_on_task") 的布尔值。会触发state_value_changed信号(针对"system_status"键,传递更新后的整个"system_status"字典)。is_game_paused() -> bool: 返回游戏是否暂停 (从"system_status"读取game_pause,若"system_status"或键不存在则返回false)。is_on_task_status() -> bool: 返回是否处于任务中状态 (从"system_status"读取is_on_task,若"system_status"或键不存在则返回false)。
对外信号 (Public Signals)
state_initialized(initial_state: Dictionary): 在initialize_for_new_game方法成功执行,内部数据被初始化后发出。传递初始化后的状态字典的副本。state_restored(restored_state: Dictionary): 在restore_state方法成功执行,内部数据被完全替换后发出。所有需要状态的功能模块都应监听此信号,以触发它们的初始化/状态恢复逻辑。传递恢复后的状态字典的副本。state_value_changed(key: String, new_value: Variant): 在set_value被调用且值发生改变时发出。可用于需要对特定状态变化做出实时反应的模块。date_changed(new_date: Dictionary): [兼容性信号] 当set_value更新了键为"time"的状态,并且其新值为字典类型时发出。主要用于保持与旧代码或特定UI(如日期显示)的兼容性。传递新日期字典的副本。
数据处理 (Data Handled)
- 核心: 管理一个包含所有动态游戏状态的 Key-Value 字典 (
_state_data)。系统级状态如暂停 (game_pause) 和是否在任务中 (is_on_task) 被存储在_state_data下的"system_status"子字典中。 - 数据规范: 不强制规定具体 Key 或 Value 的结构,由各个功能模块自行定义和管理。仅要求 Value 是可序列化的
Variant。
配置 (Configuration)
- 必须配置为 Godot 的 Autoload (单例)。
4. 存档管理器 (SaveLoadManager)
目标 (Purpose/Goal)
- 负责将
GameState提供的完整状态字典持久化存储到文件系统,以及从文件加载状态字典。 - 封装文件操作和 JSON 序列化/反序列化。
核心职责 (Responsibilities)
- 存档 (Save): 调用
GameState.get_savable_state()获取状态字典 -> 添加元数据 (存档时间, 游戏版本) -> 序列化为 JSON -> 写入user://目录下的存档文件。 - 读档 (Load): 从
user://目录读取存档文件 -> 解析 JSON 为字典 -> 验证基本结构 -> 返回提取出的game_state部分字典给调用者 (例如InitializationManager或调用它的 UI)。 - 文件管理: 管理
user://目录下的存档文件命名和存在性检查。 - 错误处理: 处理文件读写和 JSON 解析过程中的错误。
对外接口 (Public API)
save_game(slot_id: int) -> bool: 执行存档操作。调用GameState.get_savable_state()获取数据,然后写入到指定槽位的文件。返回是否成功。 (通常由存档 UI 调用)load_game(slot_id: int) -> Variant: 执行读档操作。读取指定槽位的文件,解析 JSON。成功时返回包含game_state数据的字典 (Dictionary),失败时返回null。 (通常由需要加载存档的 UI 或流程控制器调用,其结果再传递给InitializationManager.load_game_process)does_save_exist(slot_id: int) -> bool: 检查指定槽位是否存在存档文件。
对外信号 (Public Signals)
- 当前脚本未定义信号。 如果需要向 UI 提供存档/读档过程的反馈(如开始、结束、进度),可以在未来添加相关信号。
交互关键点 (Key Interactions)
- 被调用: UI (存档菜单调用
save_game,does_save_exist; 读档菜单调用load_game)。 - 调用:
GameState(仅在save_game时调用get_savable_state()),FileAccessAPI,JSONAPI,TimeAPI,ProjectSettingsAPI,OSAPI。 - 重要: 开发者在编写其他模块时,无需直接与
SaveLoadManager交互。模块的状态通过GameState间接被保存和加载。
数据处理 (Data Handled)
- 输入 (Save): 从
GameState获取的状态字典。 - 输出 (Save):
user://目录下的 JSON 文件 (包含 metadata 和 game_state)。 - 输入 (Load):
user://目录下的 JSON 文件。 - 输出 (Load): 解析后的
game_state字典 (返回给调用者) 或null。