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

前言

    找了一天没找到一个靠谱的快速锁定玩家是否装备指定饰品的方法,最后只能自己动手解决问题。如果想写kubeJS非常推荐安装KubeJS Offline Documentation,这个mod可以用指令导出一个离线文档,包含了所有的MC及其mod的java类信息,注意是java的类信息,而且只导出部分名称信息,包括类名、常量名、方法名及其参数名等,没有类的属性(有部分构造方法参数上倒是能看到几个属性名),没有类与方法的具体实现并且没有注释,搜索功能也稍显残疾,不过只看名字猜用法也足够编写js了。如果实在好奇,那就准备一个mod环境,decode一份jar包看看具体实现吧。

    如果一个事件回调的event入参包含了哪些参数你并不了解,kubeJS官方wiki也没有解释的话,推荐使用consle.info(event)(这个信息请到log下查看,[mc根目录名]/logs/)或player.tell(event)打印出event是什么java类,然后去离线文档中查看其构造方法的入参,你就明白event是由哪几个参数组成的了。

    比如EntityEvents.hurt(event => {})回调中的event打印出来显示为此类dev.latvian.mods.kubejs.entity.LivingEntityHurtEventJS,在离线文档中搜索可知其构造方法如下public LivingEntityHurtEventJS(LivingEntity entity, DamageSource source, float amount),也就是说event由实体,伤害来源,伤害值三个参数构成。

    因为我电脑没有VS也懒得装,只有IDEA,所以呢我就用笔记本写js了,当然我还是很推荐probeJS的,如果你有vs环境。

正文

    以下示例所使用mc版本及各mod版本号为,

        mc1.19.2

        forge 43.4.4

        kubejs-forge-1902.6.2-build.73.jar

        curios-forge-1.19.2-5.1.6.3.jar

        spore_1.19.2_2.1.1.jar

    提供一种快速查找是否装备某一饰品的方法,curiosHelper.findFirstCurio(entity, 物品ID),返回值为java.util.Optional<top.theillusivec4.curios.api.SlotResult>,如果没装备指定物品将返回一个空的Optional容器,可以通过调用Optional类的isPresent()方法确定是否为空,如果装备了将返回一个装有SlotResult对象的容器,使用toString可以看到装备物品所在栏位,玩家信息,玩家坐标,物品id......等信息。如果不明白什么是SlotResult,那这时离线文档就有用了,在离线文档中搜索top.theillusivec4.curios.api.SlotResult,看看它能做些什么吧,不在此赘述。

KubeJS6关于Curios快速确定是否装备某饰品的一种方案-第1张图片


    以下是一个为真菌感染:孢子(Fungal Infection:Spore)的防毒面具添加饰品栏head标签,并在装备于饰品栏时免疫菌丝感染效果的示例。

const curiosHelper = Java.loadClass("top.theillusivec4.curios.api.CuriosApi").getCuriosHelper()

//entity是否装备了饰品id为curioId的饰品
//return boolean
function isEquippedCurio(entity, curioId) {
    return curiosHelper.findFirstCurio(entity, curioId).isPresent()
}

ServerEvents.tags("item", event => {
    event.add("curios:head", "spore:gas_mask")
})

EntityEvents.hurt(event => {
    let {entity, source, amount} = event
    //不为玩家时return
    if ( !entity.class.toString().contains("ServerPlayer") ) {
        return
    }

    //佩戴面具时伤害来源为菌丝感染效果时取消伤害判定
    if ( isEquippedCurio(entity, "spore:gas_mask") ) {
        if ( source.toString().contains("mycelium.overtake") ) {
            event.cancel()
        }
    }
})

PlayerEvents.tick(event => {
    let player = event.player
    
    //佩戴面具并具有菌丝感染效果时移除菌丝感染
    if ( isEquippedCurio(player, "spore:gas_mask") ) {
        if (player.hasEffect("spore:mycelium_ef")) {
            player.removeEffect("spore:mycelium_ef")
        }
    }
})