简介

众所周知,event.player会根据前面的事件选中指定的玩家,event.player.mainHandItem会在这个玩家的基础上记录玩家主手的物品,我们不难发现,"."作为后缀的标志,是能根据条件一层层筛选所需的数据的,比方说,所有最终输出为方块数据的(需合法)事件,都可以在block或者……Block后面加上.x读取方块的x坐标,加上.blockState读取方块状态,那根据这个原理我们可以轻松实现读取任意一个位置的物品的nbt。

一种游戏内快速获取数据的方式

首先,当你需要直接获取信息性数据的时候,你应该在ItemEvents.rightClicked事件中使用event.server.runCommandSilent(`${ }`)事件,花括号里可以放event或者是变量(鼠标悬停以查看是不是可用的变量),这样当你随便手持一个物品右键的时候,屏幕左侧就会收到服务端的消息,系统会将读取到的数据转换成字符串发送到服务器。那么,我们可以输入以下代码:

ItemEvents.rightClicked(event => {
    event.server.runCommandSilent(`say ${event.player.headArmorItem}`)
})

检测玩家身上的装备的纹饰类型

现在,已知event.player.head/chest/legs/feetArmorItem可以分别获取玩家身上四个装备栏的物品数据,当玩家装备了铜头盔,用脚本获取headArmorItem时,就会收到这个提示:纹饰效果与饰品效果  kubejs基础小技巧:利用.nbt后缀读取nbt数据的技巧-第1张图片

显然,这个是没有检测nbt的,那么,我们给event.player.headArmorItem后面加上.nbt后缀会发生什么呢?纹饰效果与饰品效果  kubejs基础小技巧:利用.nbt后缀读取nbt数据的技巧-第2张图片

如果加上附魔,这个只能更长,那有没有办法截取纹饰部分呢?答案是有,不过不是JavaScript本身的截取字符串,而是kubejs提供的nbt筛选。我们再给.nbt后面加上["Trim"],那我们便可以得到这样的输出:纹饰效果与饰品效果  kubejs基础小技巧:利用.nbt后缀读取nbt数据的技巧-第3张图片

中括号是可以连续使用的,连续使用的效果是继续截取花括号下的nbt,比如

event.player.headArmorItem.nbt["Trim"]["pattern"]

会输出纹饰效果与饰品效果  kubejs基础小技巧:利用.nbt后缀读取nbt数据的技巧-第4张图片

那这样的数据已经完全够使用了,但是由于任意一个装备栏为空或者任意一个装备没有纹饰的话就会报错,因此还需要加一行

if (event.player.headArmorItem != null&&event.player.headArmorItem.nbt["Trim"]!=undefined)

现在,我们只需要写下这样的代码,就可以实现基于检测盔甲纹饰类型给予状态效果的脚本:

PlayerEvents.tick(event => {
    if (event.player.headArmorItem != null&&event.player.headArmorItem.nbt["Trim"]!=undefined)
    {var head = event.player.headArmorItem.nbt["Trim"]["pattern"]}
    else { head = null }
    if (event.player.chestArmorItem != null&&event.player.chestArmorItem.nbt["Trim"]!=undefined)
    var chest = event.player.chestArmorItem.nbt["Trim"]["pattern"]
    if (event.player.legsArmorItem != null&&event.player.legsArmorItem.nbt["Trim"]!=undefined)
    var legs = event.player.legsArmorItem.nbt["Trim"]["pattern"]
    if (event.player.feetArmorItem != null&&event.player.feetArmorItem.nbt["Trim"]!=undefined)var feet = event.player.feetArmorItem.nbt["Trim"]["pattern"]
    if (head == chest && chest == legs && legs == feet) {
        //海岸coast海豚
        if (head == "minecraft:coast")
            event.entity.potionEffects.add("minecraft:dolphins_grace", 60, 0, true, true)
        //沙丘dune速度
        if (head == "minecraft:dune")
            event.entity.potionEffects.add("minecraft:speed", 60, 0, true, true)
})

检测玩家所有饰品栏里有没有指定物品

模组:Curios API

接下来,我们可以进行一些更高端的操作,我们用

event.player.nbt

可以得到此玩家的所有nbt标签,但是由于数据过于庞大,聊天框已经放不下了,所以我们可以先清空物品栏,随便留一个方块或者物品,然后用.toString().substring(0,2000)后缀截取此字符串的前2000个字符,翻找一下不难看出,ForgeCaps下就是玩家的饰品栏数据,层层筛选过后,我们得到了这样一串代码:

event.player.nbt["ForgeCaps"]["curios:inventory"]["Curios"].toString()

那现在我们只需要从这短短的几行字符串里面找到需要的物品就行了,这里展示示例:

PlayerEvents.tick(event => {
    //indexOf是检测字符串当中第一次出现这几个字符在哪个位置,如果没有检测到即为-1
    if (event.player.nbt["ForgeCaps"]["curios:inventory"]["Curios"].toString().indexOf("kubejs:atlas") == -1) {
        //如果玩家没有地图册,那么:
        event.entity.potionEffects.add("xaeroworldmap:no_world_map", 15, 0, true, true)//禁用大地图
        event.entity.potionEffects.add("xaerominimap:no_minimap", 15, 0, true, true)//禁用小地图
        //如果要使这个效果反转,把==改成!=即可
    }
})