Skip to content
On this page

热重载与调试 ​

Katton 的开发体验围绕“修改、重载、验证”设计。把脚本放进启用的脚本包,编辑 .kt 或 .java 文件,然后无需重启游戏或服务器即可重载。

重载方式 ​

通常来说,我们使用 /katton reload 进行重载。

在 Fabric 和 NeoForge 上,它会重载服务端脚本;单人游戏中还会调度客户端脚本重载。在 Paper 上,它只重载服务端脚本包。

此外,还有以下几种触发重载的方式:

触发方式效果
/katton reload重载 Katton 脚本并显示进度条。
/reload重载数据包;Katton 会接入服务端脚本重载。
F3 + T只重载 Minecraft 客户端资源;不会调用 Katton 脚本。
脚本包界面的 Reload 按钮在 Fabric/NeoForge 客户端从界面触发重载。
IDE 桥部署Katton IDEA 插件暂存快照并通过同一条串行路径重载,见 IDE 开发连接。

编译与进度 ​

执行 /katton reload 时,Katton 0.5.1 在工作线程上准备世界包编译。客户端首次编译全局包时,也不占用渲染线程。首次编译期间,服务端重载进度会显示编译阶段。客户端激活时会复用准备好的编译产物。

如果脚本源码和依赖库未改变,Katton 可以复用磁盘中的编译缓存。稳定的宿主类路径顺序使缓存键在不同启动之间保持一致。仅修改清单不会强制重新编译 Kotlin;修改源码或包内库则会使缓存失效。阶段耗时日志分别记录编译、类路径索引、激活和资源重载。激活顺序见脚本加载生命周期。

重载时会清理什么 ​

重载时,Katton 会在再次执行入口前清理脚本持有的状态。只会清理被替换的组件:没有变化的独立脚本包会继续运行。

状态重载行为
事件监听器清理后由脚本重新注册。
托管原生监听器按脚本包作用域清理。
注入钩子在 Fabric/NeoForge 上重置。
可重载注册表清理所有权;对象软保留以避免 holder 崩溃。
数据包修改清理后在 datapack apply 阶段重新应用。
客户端渲染回调客户端重载时清理。
脚本的游戏阶段数据包接收器在 Fabric/NeoForge 上随所属包清理并重新注册。见游戏阶段网络通信。
Folia 调度任务先分离;候选提交成功后,被跳过的单次任务会重新调度。

依赖事务 ​

重载并不是所有脚本包“一刀切”。Katton 会解析 packDependencies 依赖图,计算每次变更受影响的消费者,并把工作分组成互相独立的事务:

  • 只重载消费者时,未变化的依赖实例及其共享状态会保留。
  • 重载被依赖包时,会在同一个事务中替换其消费者。
  • 互不相关的组件各自提交,因此某个组件的失败不会撤销另一个已经提交的组件。
  • 纯资源变更会保留已编译代码和运行状态,不会重放入口。

完整模型见脚本包依赖,流程见脚本加载生命周期。

生命周期与重放 ​

执行重载并不表示所有入口都会再次运行。全局包永不重放;世界包遵循注解的 replay;多人 SERVER_CACHE 包在服务器修订激活后始终全部重放。上下文中的 reason 为 HOT_RELOAD,cause 则指出是命令、数据包重载、服务器脚本包同步还是部署触发了本次调用。

完整阶段矩阵和上下文类型见脚本加载生命周期。

重载结果与回滚 ​

候选失败不会拖垮正在运行的脚本。编译错误、依赖错误和资源失败会恢复受影响组件的受管回调与资源值,但不会重放旧入口;已经提交的独立组件保持活动。

回滚只覆盖 Katton 受管状态。任意副作用——世界修改、文件写入,以及通过第三方 API 修改的静态字段——不会被撤销。重载失败后,可用 /katton errors 查看记录的诊断。