template/docs/advanced/index.md

9.4 KiB
Raw Blame History

高级 I 导览

高级教程写给已经能独立使用中级接口、现在想按自己的规则扩展数据端的人。到了这一层,问题不再是「这个接口怎么调」,而是「这个需求该放在哪一层、该由谁在什么时机执行」。弄错这一层,效果可能当下能跑,却会在存档、读档或录像回放时对不上。

这一页说明高级教程分几层、高级 I 包含哪些篇目、先读什么、以及一条贯穿全层的取舍原则:新增系统优先用插件,少改内置。

高级教程是给谁的

高级教程面向有高度定制需求的作者:

  • 你要新增一套有自己状态、生命周期和存档内容的系统,而不只是改一个数值;
  • 你要理解扩展机制本身,知道声明式接口、插件、存档与录像之间怎么配合;
  • 你愿意读一点源码,但不需要成为引擎的编写者。

它不要求你改造引擎内部。高级教程的目标是同时覆盖数据端与渲染端;渲染端尚未完工,当前只写数据端内容,渲染端部分只用占位标记指出归属。所以高级 I 的例子都落在数据端:你写的内容、你注册的对象、你声明的规则。

高级教程的三层

高级教程按难度与主题分成三层。层与顶层的中级教程不是同一套划分:中级讲「怎么用」,高级讲「怎么扩展」。

层级 定位 主要主题
高级 I · 扩展基础 以插件系统为核心,后续内容都是它的拓展 声明式接口、插件系统、可存档内容、录像一致性、data-common 的 Store、钩子深入
高级 II · 深入定制 深入定制 范围、图块、装备、录像指令、寻路、勇士与怪物属性、战斗上下文
高级 III · 原理与架构 原理与架构 双端分离约束、数据端 L0–L3、编辑器识别协议、录像深层原理、性能与调试

高级 II 已经可阅读,入口见高级 II 导览;本层收录范围、图块、装备、录像指令、寻路、属性与战斗上下文。高级 III 仍用 高级 III · <专题> 这样的占位标记指出归属,暂不提供页面入口。

高级 I 包含什么

高级 I 一共九篇,包含本导览与八篇正文。

序 篇目 它能让你做什么
1 高级 I 导览 看清分层、阅读路径与取舍原则,决定先读哪篇
2 声明式 vs 命令式接口 分清两种思路,知道持续生效的规则与一次性动作各该写在哪
3 插件系统 独立写出插件,分清数据端与渲染端的依赖和生命周期
4 可存档内容 让自定义状态正确进入存档,并在读档后恢复到存档时的样子
5 录像一致性 判断数据端哪些方法该登记、哪些路径不该记,以及检查能保证什么
6 data-common 的 Store 知道五个 Store 各存什么、能做什么,以及为什么运行时只读
7 钩子深入 把钩子限定到一个对象上,建议一个对象一个钩子实例
8 移动 Mover 能排出一次移动、等它走完,并在需要时自己实现移动器
9 FaceHandler 系列 能选对朝向处理器、算出目标格与反方向,并把朝向映射到图块数字

推荐阅读顺序:声明式 vs 命令式 → 插件系统 → 可存档内容 → 录像一致性 → data-common 的 Store → 钩子深入。移动 Mover 与 FaceHandler 系列偏参考性质,等要写移动或朝向逻辑时再读;它们各自独立,不依赖前面的顺序。

插件系统是这一层的核心,可存档内容、录像一致性、data-common 的 Store 与钩子深入都建立在它提供的扩展位置上。也可以按需求跳读,但建议至少先读前两篇:它们决定你是在「声明一条规则」,还是在「写一段一次性脚本」。

阅读路径与前置

高级 I 假设你已经读完中级教程,尤其是数据端与渲染端、代码基础、数据插件这三篇;数据端总览、钩子、录像指令也会在具体页面里被直接引用。前置篇目的链接放在本页末尾。

按目标不同,可以走两条路径:

  • 做扩展系统:声明式 → 插件 → 可存档内容 → 录像一致性。适合新增任务、商店、计数器这类有自己状态与生命周期的功能。读完能独立装配一个插件,并让它的数据跟着存档走。
  • 改内容或机制:声明式 → data-common 的 Store → 钩子深入,按需接上移动 Mover 或 FaceHandler 系列。适合在现有机制上加行为、按接口读取内容定义。读完能分清哪些只需要读、哪些由数据端登记,也能把钩子限定到目标对象上;要改移动或朝向规则时,知道该换哪个扩展点。

两条路径都建议先读声明式篇。它决定你后面是在「加一条规则」,还是「写一段一次性脚本」;这个判断错了,插件、存档与录像都会跟着别扭。

优先用插件,少改内置

新增系统优先通过插件系统实现;只有不得不修改内置系统时,才去改内部。理由很现实:版本迁移时 src 基本不会改,而内置包(packages / packages-user)有可能会改。直接改内置,升级时就要跟着差异走,维护成本更高;把改动留在自己的 src 里,升级时要对照的地方少得多。

需求类型 优先做法 什么情况下才改内置
新增一套有自己状态、生命周期与存档内容的系统 写成插件,在插件里装配对象 现有插件已覆盖大部分能力,只差一个接口或默认值时
给已有系统补一点行为 改内置类的方法体,或加一条分支 需要替换整套策略、或改动会破坏内置行为时,才独立成类
读取内容定义(图块、道具、地图、怪物、事件) 通过 state.*Store 的接口读,不新建 Store 现有 Store 装不下,且确实需要新的系统级数据表时
给会改状态的方法补录像标记 在内置方法上加一行装饰器 需要新的录像入口或自定义录像行为时(见自定义录像指令)

判断标准不是改动多少行,而是改动落在谁的代码里:能由插件或内容定义完成的,就留在 src;必须动内置包时,尽量把差异收敛在一个方法或一条分支上,方便升级时对照。

本层不覆盖什么

  • 渲染端内容:渲染端尚未完工,高级教程当前只收录数据端内容,渲染端专题待完工后补上。
  • 高级 II 的深入定制内容:范围、图块、装备、录像指令、寻路、勇士与怪物属性、战斗上下文,见高级 II 导览。
  • 高级 III 的原理与架构:双端分离约束、数据端 L0–L3、编辑器识别协议、录像深层原理、性能与调试。
  • API 参考:接口签名与类型清单不属于教程正文。

读完这一层应该能做什么

  • 能用自己的话解释声明式与命令式的区别,并说出一个「仍然该用命令式」的场景。
  • 能拿到一个需求,判断它该做成插件,还是按现有接口读取即可。
  • 能说出一个可存档对象必须满足的三个约束:只存重建必需的数据、saveState 返回独立对象(引擎不替你深拷贝)、loadState 先清空再重建。
  • 能说明为什么建议一个对象一个钩子实例,并在回调拿到多个对象时用对象引用筛出目标。
  • 能排出一次移动、等到它结束,并在需要时实现自己的移动器或勇士顶层实现。
  • 能选对朝向处理器、算出目标格与反方向,并把朝向映射到图块数字。

继续阅读

高级 I 正文:

前置回顾(中级教程):