本篇教程由作者设定使用 CC BY-NC-SA 协议。

很久以前我在玩 1.12 的植物魔法。那时的植物魔法辞典里面有一个条目的标题叫做“魔力定量统计”,点进去只有一句话:“不存在那种东西”。直到现在,想要知道一个魔力池里的魔力究竟有多少也只能用森林法杖看个大概,虽然我知道这是植物魔法的设计理念,也知道大家平常的魔力都是过量生产的,但是作为一个魔改包作者,知道一个配方究竟需要多少魔力还是有必要的,这都建立在一个魔力池究竟能装多少魔力的基础上,因此写了下面的代码。

纯 KubeJS

onEvent('block.right_click', e => {
    let manaPools = ['botania:mana_pool', 'botania:diluted_pool', 'botania:fabulous_pool', 'botania:creative_pool']
    if((manaPools.includes(e.block.id)) && e.player.mainHandItem == 'minecraft:air'){
        let mana = e.block.entityData.mana;
        let cap = e.block.entityData.manaCap;
        if (e.block.id != 'botania:creative_pool'){
            e.server.runCommandSilent(`title ${e.player.name.getString()} actionbar {"text": "Mana: ${mana}/${cap}"}`);
        }
        else {
            e.server.runCommandSilent(`title ${e.player.name.getString()} actionbar {"text": "Mana: ∞"}`);
        }
        e.player.swingArm(MAIN_HAND);
    }
})

首先,这段代码监听了 block.right_click 事件,所以显然这是一个服务端脚本,应该放在 server_scripts 文件夹里面。

然后我们知道植物魔法有四种魔力池,这里把它们的方块 ID 都放在一个数组里面。

当玩家右键点击一个方块的时候,这段代码将检测玩家点击的方块 ID 是否属于上面提到的那个数组(这可比连写四个或判断好多了)并且玩家的主手是否是空的(你也可以改成空气以外的物品,比如森林法杖)。

接着就要获取魔力池的魔力数据了,这些数据以 NBT 的形式保存在魔力池的方块实体数据里面,用 entityData 就能访问。mana 是当前的魔力量,manaCap 是这个魔力池的魔力上限。

对于创造魔力池,特事特办,直接显示无限大,对于其他魔力池就正常显示魔力数值和容量,这是通过静默运行的指令实现的。当然也可以用 PaintAPI,但是那就麻烦多了。

最后为了让玩家有种真的是自己在操作的感觉,让玩家的手挥动一下,MAIN_HAND 是一个 KubeJS 自带的全局变量,不需要你预先声明。

最后的效果是这样:

[KJS Tricks]查看魔力池魔力的具体数值-第1张图片

如果你安装了 Jade

显然右键查看没有直接用 Jade 之类的方块信息显示模组方便,所以,如果你有安装 Jade,试试下面的代码:

let $WailaClientRegistration;
let $WailaBlockAccessor;
if (Platform.isClientEnvironment()) {
    $WailaClientRegistration = Java.loadClass('snownee.jade.impl.WailaClientRegistration');
    $WailaBlockAccessor = Java.loadClass('snownee.jade.api.BlockAccessor');
}

StartupEvents.postInit(event => {
    if (!Platform.isClientEnvironment()) return;

    $WailaClientRegistration.INSTANCE.addTooltipCollectedCallback(0, (tooltip, accessor) => {
        if (!(accessor instanceof $WailaBlockAccessor)) return;
        if (accessor.getBlockEntity() == null) return;
        if (accessor.getBlockEntity().getCurrentMana == null || accessor.getBlockEntity().getMaxMana == null) return;
        let addToTooltip = comp => tooltip['add(net.minecraft.network.chat.Component)'](comp);
        let mana = accessor.getBlockEntity().getCurrentMana();
        let cap = accessor.getBlockEntity().getMaxMana();
        addToTooltip(Text.aqua(`${Text.translate('jade.tooltip.mana').getString()}: ${mana}/${cap}`));
    });

    $WailaClientRegistration.INSTANCE.addTooltipCollectedCallback(0, (tooltip, accessor) => {
        if (!(accessor instanceof $WailaBlockAccessor)) return;
        if (accessor.getBlockEntity() == null) return;
        let blockEntity = accessor.getBlockEntity();
        if (blockEntity.getMana == null || blockEntity.getMaxMana == null || blockEntity.getBindingPos == null) return;
        let addToTooltip = comp => tooltip['add(net.minecraft.network.chat.Component)'](comp);
        let pos = blockEntity.getBindingPos();
        let mana = blockEntity.getMana();
        let cap = blockEntity.getMaxMana();
        addToTooltip(
            Text.aqua(
                `${
                    pos == null
                        ? Text.translate('jade.tooltip.notbound').getString()
                        : `${Text.translate('jade.tooltip.boundto').getString()} ${pos.x} ${pos.y} ${pos.z}`
                }`
            )
        );
        addToTooltip(Text.aqua(`${Text.translate('jade.tooltip.mana').getString()}: ${mana}/${cap}`));
    });

    $WailaClientRegistration.INSTANCE.addTooltipCollectedCallback(0, (tooltip, accessor) => {
        if (!(accessor instanceof $WailaBlockAccessor)) return;
        if (accessor.block.id != 'botania:runic_altar') return;
        let addToTooltip = comp => tooltip['add(net.minecraft.network.chat.Component)'](comp);
        let mana = accessor.getBlockEntity().getCurrentMana();
        let cap = accessor.getBlockEntity().manaToGet;
        addToTooltip(Text.aqua(`${Text.translate('jade.tooltip.mana').getString()}: ${mana}/${cap}`));
    });
});

注1:Text.translate() 里面的翻译键需要你自己写语言文件,或者直接改成硬编码。

注2:这段代码需要放到 startup_scripts 文件夹。

我最开始是在 KubeJS 的 Discord 上面看到 @DragonMaster 发的一篇用 KubeJS 让 Jade 显示结构方块信息的帖子,我觉得这应该也能用在植物魔法的方块上,所以我在植物魔法的 GitHub 上查看了魔力相关的方块实体的方法,然后改了一下 DragonMaster 的代码,效果是这样的:

[KJS Tricks]查看魔力池魔力的具体数值-第2张图片显然这段代码的效果比上面的强多了(虽然重复代码有点多),不仅可以查看任何具有魔力容量的方块的魔力数值,还能查看产能花绑定的位置。