dyodyo 发表于 2026-7-19 09:32:11

简单研究了一下附加包

这个附加包我在看什么?(WAILA)会在屏幕顶部实时显示准星所指的方块或生物的一些信息。这是怎么做到的?简单研究了一下源代码,让我有了一些发现。

首先,这个附加包是开源的,github仓库在这里,下载后在/packs/data/gametests/src目录下就能看到脚本文件。
这些脚本使用TypeScript编写,再加上原作者使用面向对象的风格,所以对一些新手来说可能不是很友好(

---

/packs/data/gametests/src/waila/core/Waila.ts 这个文件中声明了最核心的单例Waila,它控制着整个脚本系统的运行。其中processPlayer方法定义了从获取看向实体/方块到显示UI的全过程。



前面那么多代码说白了就是获取一下玩家的设置、看向的实体或方块,还有状态检查之类的。我们只用看最后两行:
这里的assessment.context存储了实体或方块显示在UI上所需的信息,finalize方法简单来说就是把它们全部做一下最终的处理。



可以看到,如果看向的东西是实体的话就调用同一个实例下的finalizeEntity方法,否则调用finalizeBlock对方块的信息进行处理。我这里只关心方块是怎么处理的,所以导航到finalizeBlock方法这里。



先处理方块的元信息,这个没什么好说的。注意下面的代码,它调用了InventoryMirror.createPrimaryIconRequest方法并将其返回的结果存储到iconRequests数组中供后续使用。这个createPrimaryIconRequest方法干了什么?



上面的4行说人话就是:如果source是方块,就把它转换成物品;如果是物品,就原封不动。反正itemStack得到的一定是一个物品。最后它返回了一个存储着物品和槽位的对象。不难联想到,之后是要在什么实体或容器上替换什么物品吗?还有这个神秘数字17,记住它,之后要考的。

回到processPlayer方法,现在已经有了所有的信息,是该把它们显示到UI上了。这个uiController.present方法有点长,我们拆成3段看。



看来我们猜对了。这里的InventoryMirror.apply方法中调用了InventoryMirror.applyRequestToSlot方法,而它又调用了container.setItem方法。熟悉一点ScriptAPI的都知道,这就是往一个容器里塞东西,而这里的容器就是玩家的物品栏。



这又给我们提供了一个信息:这个包的UI实际上是使用屏幕标题(就是命令title控制的那个)实现的。有人在那个帖子的评论区下说与横扫之刃不兼容,可能就是因为这个原因了。



通过查看资源包的JSON UI定义,可以确定是使用屏幕标题做的了。



继续代码流程,在2游戏刻(0.1秒)后把刚刚塞的物品恢复成原来的物品,这样你就不容易察觉到了。

不过,我们需要察觉到。快速写一个用于获取玩家物品栏的行为包,使用铜剑就可以物品栏数据。



装载后,在快速转动视角的同时疯狂使用铜剑,令人惊喜的一幕发生了:17号槽位中出现了黑曜石。



如果使用循环命令方块执行replaceitem entity @p slot.inventory 8 air(命令中的slot.inventory 8对应17号槽位)把物品替换成空气,我们就会发现所有的看向的方块都没有图标了。



回到编辑器中,搜索17,可以看到在ui的定义文件中也出现了它。



至于实体是怎么显示的,这我就不太知道了。可能是用JSON UI做的?目前我还对JSON UI不太熟悉,可能有万能的大佬可以解答吧(
页: [1]
查看完整版本: 简单研究了一下附加包