我在玩天境的时候发现这里到处都是妖精女仆,用 /kill 指令清掉之后马上又刷出来一大堆,这些家伙简直像蟑螂一样在无法无天地大量繁殖,必须有什么人来阻止她们!

我知道有 In Control 这样的生物生成控制模组,但是既然用 KubeJS 就能做到,也没必要再加一个模组了对吧?

EntityEvents.spawned(e => {
    if(e.entity.type == 'touhou_little_maid:fairy'){
        if(e.entity.level().dimension == 'aether:the_aether') {
            e.cancel()
        }
    }
})

这是一个服务端的事件,所以当然要放在 server_scripts 文件夹里面。

这段代码的作用很简单,检测到妖精女仆生成的时候,如果她在天境,就取消生成事件,这样就不会生成妖精女仆了,刷怪蛋也不行。

后来我在玩Alex's Caves的时候又发现,妖精女仆在原始洞穴里面也会大量生成,恐龙时代哪来的女仆,所以也应该禁止她们在这生成,但是原始洞穴在主世界,总不能让她们在主世界也禁止生成吧,前面的代码现在不好用了。

EntityEvents.spawned(e => {
    let getBiome = () => {
        let pos = new BlockPos(Math.floor(e.entity.x), Math.floor(e.entity.y), Math.floor(e.entity.z))
        return e.entity.level().getBiome(pos).unwrap().left().get().location()
    }

    if(e.entity.type == 'touhou_little_maid:fairy'){
        let biome = getBiome()
        let biomeBlackList = /(alexscaves).*/
        if(e.entity.level().dimension == 'aether:the_aether' || biomeBlackList.test(biome)) {
            e.cancel()
            if(e.player) {
                e.player.tell('You cannot spawn this entity here!')
            }
        }
    }
})

更新后的代码的重点就是 getBiome 这个函数了,原理很简单,就是在 level 中检测实体所在位置的群系,然后返回。只是那一长串的链式调用看起来很不明觉厉,下面解释一下这一串是什么意思。

  1. level() 返回一个 Level 对象;

  2. getBiome() 方法返回一个装有 Biome 对象的 Holder 对象;

  3. unwrap() 方法解包 Holder 返回一个 Either 对象,Either 对象里面有两个元素:左边是装有 Biome 对象的 ResourceKey 对象,右边是 Biome 对象,Either 对象表达一种“我里面的东西要么是左边那个,要么是右边那个”的情况,这里使用 left() 获取左边那个;

  4. 使用 left() 得到的是一个 Optional 对象,里面是一个装着 Biome 对象的 ResourceKey 对象;

  5. 使用 get() 得到其中的 ResourceKey;

  6. 使用 location() 获取 ResourceLocation;

  7. ResourceLocation 就是我们经常看到的 modid:xxx。

总而言之,经过一长串的解包之后,我们最终得到了这个实体生成时所处的群系,接着用一个正则表达式进行匹配,如果匹配成功,或者实体所在的维度在黑名单中,就阻止实体生成。

现在原始洞穴就干净多了。