3.9 KiB
3.9 KiB
弟子管理模块设计
模块位置:P1 核心循环(见 doc/Roadmap.md)。本文档描述弟子数据模型与弟子管理器的设计。
1. 结构:数据类 + 管理器
弟子模块拆分为两层:
| 层 | 文件 | 类型 | 职责 |
|---|---|---|---|
| 弟子数据类 | src/Data/Models/Disciple.gd |
RefCounted | 持有弟子的所有信息,纯数据,无逻辑 |
| 弟子管理器 | src/Character/DiscipleManager.gd |
Node | 添加、删除、查询、修改弟子属性 + 领域操作(修炼结算) |
2. 设计模式
| 角色 | 模式 | 说明 |
|---|---|---|
| 弟子数据类 | 纯数据模型 | RefCounted,运行时可变数据,不依赖场景树,可脱离场景单测 |
| 弟子管理器 | 仓储模式(Repository) | CRUD + 查询的集中入口,是弟子数据的唯一管理者 |
| 变化通知 | 观察者模式(Observer) | 管理器发信号,UI/其他系统订阅实时刷新 |
| 弟子创建 | 工厂方法(Factory) | 初始弟子/收徒的创建逻辑收在管理器内 |
明确不用的方案:
- 不用 ECS:弟子属性固定(境界/技艺/忠诚…),无动态组件需求,是过度设计。
- 不用 Resource/.tres:弟子是运行时可变数据,RefCounted 类最轻量,不走序列化资源。
- 不把所有逻辑塞进数据类:领域操作归管理器,保证修改只有单一入口,信号好通知,测试好做。
3. Disciple 数据类(RefCounted,纯数据)
var name: String
var is_mortal: bool # 凡人弟子
var realm_level: int = 1 # 境界 1-9
var cultivation_skill: int = 1 # 种植技艺 1-10
var alchemy_skill: int = 1 # 炼丹技艺 1-10
var loyalty: int = 50 # 忠诚 0-100(P1 仅存字段)
var cultivation_exp: int = 0 # 修为进度
只读派生(不存储,由属性计算):
monthly_cost() -> int:每月修炼灵石消耗(凡人弟子为 0)realm_name() -> String:境界显示名(凡人 / 炼气X层…)exp_to_next() -> int:升到下一境界所需修为
4. DiscipleManager 管理器(Node,仓储)
signal disciple_added(disciple)
signal disciple_removed(disciple)
signal disciple_attr_changed(disciple, attr_name, old_value, new_value)
func add_disciple(d) -> void
func remove_disciple(d) -> void
func get_disciple(id) -> Disciple
func get_all() -> Array[Disciple]
func get_by_realm(level) -> Array[Disciple]
func count_mortals() -> int
func set_attr(d, attr, value) -> void # 修改唯一入口,内部发信号
func settle_month() -> void # 修炼结算(领域操作)
func to_dict() -> Dictionary # 存档网关
func load_from_dict(d) -> void
5. 关键设计决策
- 修改只走管理器——
set_attr()是唯一变更入口,内部统一发disciple_attr_changed。UI 订阅它实时刷新,也为以后忠诚度/事件系统留监听点。 - 查询返回引用——性能好(P1 规模无碍),但禁止外部直接写属性;要写必须走管理器。
- 管理器是 Node,数据类是 RefCounted——管理器可挂 MainGame/测试场景;数据类脱离场景树也能单测。
- 领域操作在管理器——
settle_month()(修炼消耗灵石、增加修为、境界提升)归管理器,数据类不碰业务逻辑。 - 存档网关(Unit of Work)——序列化/恢复只经过管理器
to_dict()/load_from_dict(),为 SaveSystem 注册预留。
6. 测试方式
独立测试场景 src/Character/test_disciple.tscn:
- 实例化 DiscipleManager(不依赖其他模块)
_ready()中自动执行用例:- 添加/删除弟子 → 信号是否正确发出
- 查询(get_by_realm / count_mortals)
set_attr→ 信号带旧值/新值settle_month→ 境界提升/灵石消耗正确to_dict / load_from_dict往返一致
print输出 PASS/FAIL,编辑器直接运行场景验证