docs(10-18): 编写高级 I 导览

This commit is contained in:
unanmed 2026-10-20 14:54:56 +08:00
parent b7c8866948
commit 4dcac2f80a

100
docs/advanced/index.md Normal file
View File

@ -0,0 +1,100 @@
# 高级 I 导览
高级教程写给已经能独立使用中级接口、现在想按自己的规则扩展数据端的人。到了这一层,问题不再是「这个接口怎么调」,而是「这个需求该放在哪一层、该由谁在什么时机执行」。弄错这一层,效果可能当下能跑,却会在存档、读档或录像回放时对不上。
这一页说明高级教程分几层、高级 I 包含哪些篇目、先读什么、以及一条贯穿全层的取舍原则:新增系统优先用插件,少改内置。
## 高级教程是给谁的
高级教程面向有高度定制需求的数据端作者:
- 你要新增一套有自己状态、生命周期和存档内容的系统,而不只是改一个数值;
- 你要理解扩展机制本身,知道声明式接口、插件、存档与录像之间怎么配合;
- 你愿意读一点源码,但不需要成为引擎的编写者。
它不要求你懂渲染端实现,也不要求你改造引擎内部。高级 I 的所有例子都落在数据端:你写的内容、你注册的对象、你声明的规则。
## 高级教程的三层
高级教程按难度与主题分成三层。层与顶层的中级教程不是同一套划分:中级讲「怎么用」,高级讲「怎么扩展」。
| 层级 | 定位 | 主要主题 |
| --------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------- |
| 高级 I · 扩展基础 | 以插件系统为核心,后续内容都是它的拓展 | 声明式接口、插件系统、可存档内容、录像一致性、data-common 的 Store、钩子深入 |
| 高级 II · 系统实现 | 系统级实现 | 战斗上下文、光环 / 查询 / 优先级、伤害与地图伤害、渲染层与布局、加载与插件生命周期、自定义录像行为 |
| 高级 III · 原理与架构 | 原理与架构 | 双端分离约束、数据端 L0–L3、编辑器识别协议、录像深层原理、性能与调试 |
当前站点的「高级教程」只收录高级 I 的内容。高级 II 与高级 III 的专题在正文里用 `高级 II · <专题>`、`高级 III · <专题>` 这样的占位标记指出归属,不提供页面入口。
## 高级 I 包含什么
高级 I 一共七篇,包含本导览与六篇正文。
| 序 | 篇目 | 它能让你做什么 |
| --- | -------------------- | ------------------------------------------------------ |
| 1 | 高级 I 导览 | 看清分层、阅读路径与取舍原则,决定先读哪篇 |
| 2 | 声明式 vs 命令式接口 | 分清两种思路,知道持续生效的规则与一次性动作各该写在哪 |
| 3 | 插件系统 | 独立写出插件,处理依赖、生命周期、id 稳定性与版本迁移 |
| 4 | 可存档内容 | 让自定义状态正确进入存档,并在读档后恢复到存档时的样子 |
| 5 | 录像一致性 | 判断哪些方法该登记、哪些路径不该记,以及检查能保证什么 |
| 6 | data-common 的 Store | 理解四个内容注册表各存什么,以及为什么运行时只读 |
| 7 | 钩子深入 | 在多地图、多图层、多移动器的场景里限定钩子的身份 |
推荐阅读顺序:声明式 vs 命令式 → 插件系统 → 可存档内容 → 录像一致性 → data-common 的 Store → 钩子深入。
插件系统是这一层的核心,后四篇都建立在它提供的扩展位置上。也可以按需求跳读,但建议至少先读前两篇:它们决定你是在「声明一条规则」,还是在「写一段一次性脚本」。
## 阅读路径与前置
高级 I 假设你已经读完中级教程,尤其是数据端与渲染端、代码基础、数据插件这三篇;数据端总览、钩子、录像指令也会在具体页面里被直接引用。前置篇目的链接放在本页末尾。
按目标不同,可以走两条路径:
- <strong>做扩展系统</strong>:声明式 → 插件 → 可存档内容 → 录像一致性。适合新增任务、商店、计数器这类有自己状态与生命周期的功能。读完能独立装配一个插件,并让它的数据跟着存档走。
- <strong>改内容或机制</strong>:声明式 → data-common 的 Store → 钩子深入。适合补图块、改事件、在现有系统上加行为。读完能判断一条定义该在加载期登记还是运行期只读,也能把钩子限定到目标对象上。
两条路径都建议先读声明式篇。它决定你后面是在「加一条规则」,还是「写一段一次性脚本」;这个判断错了,插件、存档与录像都会跟着别扭。
## 优先用插件,少改内置
新增系统优先通过插件系统实现;只有不得不修改内置系统时,才去改内部。理由很现实:版本迁移时 `src` 基本不会改,而内置包(`packages` / `packages-user`)有可能会改。直接改内置,升级时就要跟着差异走,维护成本更高;把改动留在自己的 `src` 里,升级时要对照的地方少得多。
| 需求类型 | 优先做法 | 什么情况下才改内置 |
| -------------------------------------------- | ------------------------------ | --------------------------------------------------------------------- |
| 新增一套有自己状态、生命周期与存档内容的系统 | 写成插件,在插件里装配对象 | 现有插件已覆盖大部分能力,只差一个接口或默认值时 |
| 给已有系统补一点行为 | 改内置类的方法体,或加一条分支 | 需要替换整套策略、或改动会破坏内置行为时,才独立成类 |
| 注册一组内容定义(图块、道具、地图、事件) | 在加载期集中登记,不新建 Store | 现有四个 Store 装不下,且确实需要新的系统级数据表时 |
| 给会改状态的方法补录像标记 | 在内置方法上加一行装饰器 | 需要新的录像入口或自定义录像行为时(属于 `高级 II · 自定义录像行为`) |
<strong>如果你不怎么懂代码,优先改内置已有实现,而不是自己造一套。</strong>在内置类里补几行,出问题时对照原代码就能看出差异;新建插件或新类要同时处理注册、依赖、时机与存档 id,排查面大得多。
## 本层不覆盖什么
- <strong>渲染端内容</strong>:渲染端尚未完工,高级 I 只写数据端。
- <strong>高级 II 的系统级实现</strong>:战斗上下文、光环 / 查询 / 优先级、伤害与地图伤害、渲染层与布局、加载与插件生命周期、自定义录像行为。
- <strong>高级 III 的原理与架构</strong>:双端分离约束、数据端 L0–L3、编辑器识别协议、录像深层原理、性能与调试。
- <strong>API 参考</strong>:接口签名与类型清单不属于教程正文。
## 怎么验证你读懂了
- 能用自己的话解释声明式与命令式的区别,并说出一个「仍然该用命令式」的场景。
- 能拿到一个需求,判断它该做成插件、改内置,还是只需补一条内容定义。
- 能说出一个可存档对象必须满足的三个约束:只存重建必需的数据、`saveState` 返回深拷贝、`loadState` 先清空再重建。
- 能判断一个钩子会不会被非目标对象触发,并说出该用「每对象一个实例」还是「共享实例 + `===`」。
## 继续阅读
高级 I 正文:
- [声明式 vs 命令式接口](./declarative-vs-imperative.md)
- [插件系统](./plugin-system.md)
- [可存档内容](./saveable-content.md)
- [录像一致性](./replay-consistency.md)
- [data-common 的 Store](./data-stores.md)
- [钩子深入](./hooks-in-depth.md)
前置回顾(中级教程):
- [数据端与渲染端](../intermediate/data-vs-render.md)
- [代码基础](../intermediate/code-basics.md)
- [数据插件](../intermediate/data-plugins.md)