脚本包同步与信任
Fabric/NeoForge 多人服务器会在登录时以及服务端成功热重载后持续同步客户端脚本包。Paper 没有 Katton 客户端,因此不提供客户端同步。
当前网络协议为 v4。协议不兼容的对端会在配置阶段握手时被拒绝,并提示 Incompatible Katton pack protocol; update client/server and rebuild the v4 cache。服务器分桶缓存位于 serverpacks-v4,旧的 serverpacks 目录会被忽略并重建,而不会复用。
同步哪些内容
同步的包就是它的完整逻辑内容:源码、assets/**、data/**、直接的 libs/*.jar、音频文件以及其他任何内容。只有 manifest.json 会被单独作为清单处理,本地 .kattonpack.state.json 永远不属于包内容。完整内容规则与上限见清单、依赖与签名。
因此包内音频不需要额外的下载通道,它就是普通的签名内容,AudioSource.packFile 会从缓存的修订中解析它。单文件上限 16 MiB,单批次最多 16,384 个文件、64 MiB 内容。
登录:配置阶段修订 0
登录同步保留在配置阶段,因为客户端注册表设置必须在注册表校验前完成:
- 服务端收集清单中
"clientSync": true的已启用脚本包。 - 服务端把完整哈希快照作为修订
0发送。 - 快照非空时,服务端立即发送完整包内容,不等待客户端请求往返。
- 客户端校验签名、哈希、信任状态及客户端适用依赖。
- 客户端在注册表校验继续之前编译并激活该快照。
即使快照为空也会发送哈希列表,以便客户端停用上次连接留下的旧缓存包。
从 0.5.1 起,如果连接正在等待脚本重载,服务端会暂停慢登录超时计时。因此,首次 Kotlin 编译不会占用该超时时间。下文在线修订的 30 秒回执超时不受影响。
在线重载:游戏阶段修订
每次服务端脚本热重载成功后,服务端都会向远程玩家发布单调递增的游戏阶段修订:
- 服务端发送新修订的完整哈希快照。
- 客户端与当前活动修订比较,只请求已变化或缺失的包。
- 未变化的包复制进暂存快照;下载的差量在签名和哈希校验后写入。
- 客户端校验清单依赖并预编译完整暂存快照。
- 只有准备全部成功后才激活候选快照。
- 所有活动
SERVER_CACHE包都会重放入口,包括未变化的包以及写了replay = false的入口。 - 客户端回执成功;失败回执或 30 秒超时会导致该玩家断开连接。
新哈希快照中未出现的包会被停用。空快照合法,并会停用全部服务器缓存包。
激活是事务式的:拒绝信任、签名或哈希无效、下载不完整、依赖错误及编译失败都会保留上一活动修订。候选快照准备完成前,Katton 不会清理仍在工作的客户端监听器。
由于包与包之间的依赖必须位于同一份同步集合内,SERVER_CACHE 包只能依赖另一个 SERVER_CACHE 包。任何会伸到快照之外的依赖,都会在服务端发布修订之前被拒绝。
集成式单人游戏不会把脚本包通过内存网络传给自己,本地客户端直接从相同的本地包重载;独立服务器客户端才使用上述网络协议。
如果脚本需要在游戏阶段自行发送消息,见游戏阶段网络通信。这些逻辑频道不会改变本页的脚本包同步协议。
缓存位置
配置阶段修订 0 使用服务器分桶缓存。在线修订暂存于:
<游戏目录>/serverpacks-v4/<sha256(服务器地址)>/revisions/<revision>/<base64url(syncId)>/每个缓存包目录都包含自己的 manifest.json,并保持与源包相同的相对文件结构,因此 AudioSource.packFile("audio/theme.mp3") 可以相对缓存修订解析。
信任库位于:
<游戏目录>/.katton/remote-script-trust.json信任库记录受信任服务器与签名密钥。如果已信任的 keyId 后续给出不同的内嵌公钥,Katton 会拒绝远程脚本。
签名与哈希
签名使用 Ed25519 载荷 版本 3,它对同步 ID、作用域、移除 signature 后的清单 JSON、文件数量以及按路径排序的每个路径/内容对添加长度前缀。即使二进制内容包含零字节,帧格式也不存在歧义。旧版载荷 1 与 2 会被拒绝,请用当前的 Katton-Sign 插件重新签名迁移。
客户端会在把包写入缓存前验证签名,然后把缓存哈希与服务端声明的哈希列表比对。哈希用于发现缓存不一致,签名用于按密钥校验内容;二者都不能证明服务器或脚本作者安全。
安全模型
远程 Katton 脚本是在 Minecraft 客户端内运行的任意 JVM 代码。因此远程执行前的信任确认会阻塞流程,要求玩家明确批准。
接收客户端会独立校验自身适用的清单依赖。服务端安装了某个依赖,并不代表客户端也安装了对应模组。
纯服务端脚本包如果不包含客户端入口、客户端所需注册表定义、资源、渲染代码或音频,应设置 "clientSync": false。
