Cat_Anchor 发表于 2026-5-29 19:37:40

SAPI 的时序与 kit 命令

本帖最后由 Cat_Anchor 于 2026-5-29 19:45 编辑

> ---
>
> 开始正题之前,我想先分享一些好玩的字符。
>
> 大家真的认真看过下面这些字符吗?
>
> 有时候,这些字符的使用会起到意想不到的效果。
>
> ---












---

我们都知道,使用 SAPI 时,有三种执行权限:早期执行、受限执行和普通执行。早期执行用于注册自定义组件、命令或维度,受限执行可以用于 before 事件和命令回调,而普通执行适用于 after 事件和其他大部分场景。那些标注了“世界修改”的 API 就不能在受限执行中访问,因为受限执行阻止世界状态的改变。多数情况下,可以改变世界状态的 API 就是世界修改的 API,例外是 `sendMessage()`,它不属于世界修改的 API,即使在早期执行中也可以调用。

我们已经知道,API 的执行是瞬时的,例如 `block.setType()` 会立刻将这个方块设为参数中指定的类型。那么如果在调用 `setType()` 后再调用一次,但是传入不同参数,最后方块就会被设为后者的类型。这一切都在 1 tick 内发生,属于一次游戏循环的一部分,所以看不出方块变化的过程。

另外,我们很容易注意到 `Block` 类是对特定位置方块的引用,它不代表方块本身,它代表维度中在那个位置的任意方块。它是方块之下更基础的部分,也就是所谓“方块网格”的一个单元格。

那么产生这样一个问题:如果我们在 1 tick 内放置一个箱子,在箱子里放一些物品,然后用结构保存这个箱子,最后清除物品和箱子,结构中是否会有箱子?

“有”,这似乎是个显而易见的答案。前面说过 API 在 1 tick 内按调用顺序执行,那么结构保存时读取的应该是世界中箱子的数据,虽然那时候我们看不到它。

但事实证明,结构中不存在任何箱子。反复尝试十几次,结果始终不变。

我不清楚这是什么导致的,不过我倾向于相信这是因为执行的延迟。也许 API 并不总是在它们被调用的那一 tick 中执行,因为将清除箱子的步骤推迟 1 tick 执行后,结构中就有箱子了。也许正是这 1 tick 给了引擎执行的时间,刷新了世界状态,最后使整段代码正常工作。

这就是 `kit` 命令背后的故事。它是万象添补 0.17.21 中的新命令,用于保存或加载玩家的快捷栏。它只接受一个“槽位”字符串参数,指定了快捷栏保存到的位置。

每个槽位都是一个单方块结构,其中的箱子会存储玩家的快捷栏。每次执行 `kit <slot: string>` 的时候,都会将玩家的快捷栏与箱子容器的前面九个槽位互换,与原版展示架的逻辑类似。这样,我们就避免了创建两个子命令,也避免了麻烦的操作步骤。

比如,现在我们快捷栏中装满圆石,而且从未使用过 kit 命令。执行 `/kit a` 会将所有圆石存储到 `a` 槽位中,同时玩家快捷栏清空。这时,将玩家快捷栏填满蜂蜜块,再次执行 `/kit a` 命令,玩家的快捷栏将变为充满圆石,同时 `a` 槽位中充满蜂蜜块。接下来不断执行 `/kit a`,玩家的快捷栏将在蜂蜜块和圆石之间切换。

这种互换的逻辑很巧妙。如果我们拿出一些命令执行器,设置命令得当的话,就可以模拟“文件系统”,只不过所谓的文件现在都是快捷栏中的物品。

牢冥王 发表于 2026-5-29 23:41:26

我记得原来文档注明了自定义属性还是什么内容来着,在同一次执行过程中,它的get方法只能读取set方法修改前的数据。那个结构也应该是只能读取修改前的方块[抖音_494]
页: [1]
查看完整版本: SAPI 的时序与 kit 命令