Skip to content

LootJs

LootJs 是一个KubeJS附属模组,它为KubeJS对于原版战利品列表修改进行了更方便的操作 KubeJS本身自带的修改 Loot 的方法过于繁琐,若要修改关于:

  • 方块
  • 实体
  • 战利品列表

内的 LootTable

推荐使用LootJs来实现

简介

除了操作 之外,LootJs还可以使用条件来应用过滤器。

如果某个条件不成立,则在条件不成立之后不会触发任何操作。可以串联多个条件,以将更多过滤器应用于您的战利品修改器。

开始此篇之前,你需要记住这几个网址

EntityPredicateBuilderJS

DamageSourcePredicateBuilderJS

此篇内容中会讲述到对应的 BuilderJS,可以翻阅此链接进行查看

匹配战利品

matchLoot(ItemFilter, exact)

语句matchLoot()放置在addLoot()之前生效

ItemFilter填入你要匹配的物品 ID

传参exact可选择,若为true,则该物品战利品列表里面的所有物品要满足条件后才会进行修改

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:cow")
        .matchLoot("minecraft:leather") // true / false
        .addLoot("minecraft:diamond");
});

上述示例代码,对应minecraft:cow的战利品列表,若minecraft:cow的战利品列表满足了拥有minecraft:leather,则添加一个新的战利品minecraft:diamondminecraft:cow,若不满足该条件,则不会添加新的战利品

匹配主手物品

matchMainHand(ItemFilter)

匹配主手物品为一个ItemFilter,当你要匹配的主手物品带有耐久的时候,建议使用Item.of().ignoreNBT()来忽略物品的耐久度

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("#forge:ores")
        .matchMainHand(Item.of("minecraft:netherite_pickaxe").ignoreNBT())
        .addLoot("minecraft:gravel");
});

匹配副手物品

matchOffHand(ItemFilter)

匹配副手物品为一个ItemFilter,当你要匹配的副手物品带有耐久的时候,建议使用Item.of().ignoreNBT()来忽略物品的耐久度

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("#forge:ores")
        .matchOffHand(Item.of("minecraft:netherite_pickaxe").ignoreNBT())
        .addLoot("minecraft:gravel");
});

匹配装备

matchEquip(slot, ItemFilter)

匹配玩家身上的装备,包括头部,胸部,腿部,脚以及主副手符合条件后,进行战利品列表修改

无视耐久检测,可以加上Item.of().ignoreNBT()来取消对耐久的匹配

slot对应的属性有:

  • MAINHAND 主手
  • OFFHAND 副手
  • FEET
  • LEGS 腿部
  • CHEST 胸部
  • HEAD 头部
js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("#forge:ores")
        .matchEquip(
            "MAINHAND",
            Item.of("minecraft:netherite_pickaxe").ignoreNBT()
        )
        .addLoot("minecraft:gravel");
});

匹配实体

matchEntity(callback)

matchEntity()语句通过回调函数来进行实体的匹配,例如当实体拥有对应的 NBT 或者状态后,进行战利品修改,反之则不进行修改

与死亡、打开箱子或破坏方块的实体匹配

LootJs将在您的回调函数中提供EntityPredicateBuilderJS以进行匹配。

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .matchEntity((entity) => {
            entity.isInWater(true);
        })
        .addLoot("minecraft:diamond");
});

以上的代码示例检测minecraft:creeper是否处于水中,若处于水中,则为该实体添加战利品minecraft:diamond掉落+

匹配直接击杀者

matchDirectKiller(callback)

直接击杀者以及间接击杀者的关系,例如玩家射箭杀死了一只僵尸:

  • 僵尸是被击杀者
  • 箭是直接击杀者
  • 玩家却是间接击杀者

因为是箭杀死的僵尸,而不是玩家杀死的僵尸,但是箭是玩家射出的,所以玩家属于间接击杀者

相较于匹配实体,matchDirectKiller()是匹配直接击杀者的条件

下面的示例代码检查直接击杀者是否在水中击杀了被击杀者,若击杀者在水中,则给被击杀者添加一个战利品掉落minecraft:diamond

反之若击杀者未处于水中,则不会给被击杀者添加一个战利品掉落

同样的道理,LootJs给回调函数提供的依旧是EntityPredicateBuilderJS以进行匹配

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .matchDirectKiller((entity) => {
            entity.isInWater(true);
        })
        .addLoot("minecraft:diamond");
});

匹配间接击杀者

matchKiller(callback)

相较于匹配直接击杀者,而matchKiller()匹配的是间接击杀者的条件

击杀者不管是弹射物还是玩家,最终都已间接造成伤害的击杀者为准

上述检查直接击杀者的代码中,若使用弓箭在地面对minecraft:creeper进行射击,不会添加新的战利品给minecraft:creeper 只有在水中射击(箭矢在水中击杀生物,且未离开水面),才会给minecraft:creeper添加一个新的战利品

下面的示例代码中,只会匹配间接击杀者的状态,即玩家,不会匹配箭矢的状态.当间接击杀者的状态符合条件后,对被击杀者添加新的战利品

同样的道理,LootJs给回调函数提供的依旧是EntityPredicateBuilderJS以进行匹配

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .matchKiller((entity) => {
            entity.isInWater(true);
        })
        .addLoot("minecraft:diamond");
});

匹配玩家

matchPlayer(callback)

相较于上述的直接击杀者,间接击杀者,而matchPlayer匹配玩家的条件.

LootJs给回调函数提供的依旧是EntityPredicateBuilderJS以进行匹配

下述代码中,直接检测玩家是否在水中并生成对应的战利品掉落

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .matchPlayer((player) => {
            player.isInWater();
        })
        .addLoot("minecraft:diamond");
});

匹配伤害来源和类型

matchDamageSource(callback)

上述三种匹配类型是根据拥有对应的条件后才会进行战利品的生成

matchDamageSource()是针对于伤害的类型,以及来源来进行匹配,并生成对应的战利品

LootJS将提供DamageSourcePredicateBuilderJS给回调函数中进行匹配

下面的示例代码中,将检测对minecraft:creeper的伤害类型是否是铁砧掉落,若是则添加一个新的战利品给minecraft:creeper

anvil修改为arrow后就是检测来自箭矢的伤害类型

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .matchDamageSource((source) => {
            source.anyType("anvil");
        })
        .addLoot("minecraft:diamond");
});

更多的伤害类型请查阅 Minecraft Wiki 进行获取

and ? is ? or ? isNot ? invert ? matchDirectEntity ? matchSourceEntity ?

爆炸检查

survivesExplosion()

survivesExplosion()语句添加了对能在爆炸中不会消失的方块的检查

若 TNT 一类的爆炸物品对该方块不会造成消失,则会添加一个战利品给这个方块

若爆炸后方块会消失,则该方块不会被添加 Loot

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .survivesExplosion()
        .addLoot("minecraft:gravel");
});

tick 检查

timeCheck(period, min, max)

timeCheck(min, max)

下列示例代码对砂砾添加了一个时间检测:

  • 24000 是周期period,对应一个完整的游戏循环,即一天
  • 0 是最小值(min),表示日出时间
  • 9000 是最大值(max),大约对应游戏的上午时分
js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .timeCheck(24000, 0, 9000)
        .addLoot("minecraft:diamond");
});

这串代码演示了:只有在游戏内的早晨时间(大约从日出到上午)破坏沙砾时,有机会掉落钻石

若不添加period,检查游戏世界的总时间是在所指定的(min,max)刻之间

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .timeCheck(0, 12000)
        .addLoot("minecraft:diamond");
});

添加period以及不添加period的区别:

  • 使用 period 时,检查的是period周期内的相对时间
  • 不使用 period 时,检查的是游戏世界从min刻到max刻的总时间

例如上述代码period传参为 24000,即检查一整天的 tick(24000)内对应的 0-9000 tick

不使用 period 的时候,检测的是当天 tick 内对应的 0-12000 tick

天气检查

weatherCheck(value)

weatherCheck()语句对应传入的参数是:

  • raining 雨天
  • thundering 雷雨天

注意,要使用{}进行包裹

json
{
    "raining": true, // false
    "thundering": true // false
}

下面的示例代码描述的是在雨天的时候挖掘砂砾会掉落钻石

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .weatherCheck({
            raining: true,
        })
        .addLoot("minecraft:diamond");
});

若检测为雷雨天,则将raining更换为thundering,若要检测是否为晴天的时候,将raining以及thundering两个都设置为false即可

随机概率

randomChance(value)

randomChance()语句对应的传入参数为float

用来设置战利品的掉落概率

下面的示例代码描述的是:玩家挖掘砂砾后,有 30%的概率会掉落钻石

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .randomChance(0.3) // 30%
        .addLoot("minecraft:diamond");
});

抢夺附魔随机概率

randomChanceWithLooting(value, looting)

randomChanceWithLooting()传入的参数为value即概率,looting即抢夺附魔的等级

下面的示例代码描述的是:玩家手持附魔了抢夺 2 的工具,破坏砂砾后有 30%的概率掉落钻石

这个方法仅适用于方块,对生物使用randomChanceWithLooting()方法会出现一个奇怪的 bug:不管概率以及附魔等级是否指定,都会添加战利品到生物的战利品池中. 相当于对生物使用这个方法和没使用是一样的效果

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .randomChanceWithLooting(0.3, 2) // 30%
        .addLoot("minecraft:diamond");
});

附魔随机概率

randomChanceWithEnchantment(enchantment, [chances])

randomChanceWithEnchantment()语句的用途是指定手上物品的附魔 ID 以及附魔等级来进行战利品列表的修改

传入的参数enchantment对应附魔的 ID,后面的数组[chances]对应的是附魔的等级

值得注意的是[chances]的计算是从该物品没有附魔,即 0 等级的附魔开始计算,例如:

  • 效率 5 [0, 0.05, 0.05, 0.1, 0.3, 0.5]对应的是效率附魔等级 0-1-2-3-4-5 级
  • 0 级为 0%,1 级为 5%,2 级为 5%,3 级为 10%,4 级为 30%,5 级为 50%
  • 时运 3 [0, 0.1, 0.4, 0.5]对应的是时运附魔等级的 0-1-2-3 级
  • 0 级为 0%,1 级为 10%,2 级为 40%,3 级为 50%

附魔等级有多少,数组里面的数字就填多少个,如果数组里面的数字数量超出了附魔等级,游戏则会报错

官方示例:

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .randomChanceWithEnchantment("minecraft:looting", [0, 0.1, 0.5, 1])
        .addLoot("minecraft:diamond");

    /*
        [0, 0.1, 0.5, 1]:
          0% for no looting
         10% for looting 1
         50% for looting 2
        100% for looting 3
    */
});

生物群系检查

biome(...biomes)

biome()语句传入的参数为对应的生物群系 ID,或者Tag,即在生物群系之前加上#来标记为Tag

如果给出了多个biome,则所有的生物群系必须匹配,若一个不匹配则不会进行战利品添加

官方示例:

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .biome("minecraft:jungle")
        .addLoot("minecraft:diamond");
});

生物群系检查 2

anyBiome(...biomes)

anyBiome()语句传入的参数和biome()语句传入的参数大相径庭

只是功能上进行了区别:

  • biome()语句若指定了多个生物群系,则所有的群系条件必须满足,不满足则不会添加战利品
  • anyBiome()语句若指定了多个生物群系,则至少有有一个生物群系匹配,才会添加战利品.若一个都不匹配,则不会添加战利品

官方示例:

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .anyBiome("minecraft:jungle", "#minecraft:is_forest")
        .addLoot("minecraft:diamond");
});

维度检查

anyDimension(...dimensions)

anyDimension()语句传入的参数为维度 ID

  • minecraft:overworld 主世界
  • minecraft:the_nether 下界
  • minecraft:the_end末地

或者传入玩家的自定义维度modid:dimensions_name

当玩家处于所指定的维度时,才会添加对应的战利品

官方示例:

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .anyDimension("minecraft:nether")
        .addLoot("minecraft:diamond");
});

结构检查

anyStructure([structures], exact)

anyStructure()语句传入的参数为structures(结构 ID)以及exact(boolean)

玩家只有在进入特定的结构时,才会添加对应的战利品

structures可以写成一个数组来进行多个结构指定.

exact的作用是

  • false 只会检查玩家是否在结构边界内
  • true 检查玩家是否在结构内(例如村庄中的房屋)

官方示例:

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .anyStructure(["minecraft:stronghold", "minecraft:village"], false)
        .addLoot("minecraft:diamond");
});

亮度检查

lightLevel(min, max)

lightLevel()语句传入的参数为两个整数,即 0-15 之间

通过检测方块的亮度来进行战利品的添加

官方示例:

js
LootJS.modifiers((event) => {
    event
        .addBlockLootModifier("minecraft:gravel")
        .lightLevel(0, 15)
        .addLoot("minecraft:diamond");
});

玩家击杀检查

killedByPlayer()

该语句不需要传入任何参数,单纯是一个检测的方法

该方法只适用于对生物的战利品修改

检测生物是否被玩家击杀,如果是玩家击杀,则添加对应的战利品

官方示例:

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .killedByPlayer()
        .addLoot("minecraft:diamond");
});

击杀者距离检测

distanceToKiller(interval)

distanceToKiller()传入的参数为$MinMaxBounds$Doubles$Type,只需要填入数字即可

检测被击杀者与击杀者的距离,若击杀者位于所制定的范围之外,则会生成对应的战利品.若在指定的范围内,则不会生成战利品

下面的示例代码中,若玩家在minecraft:villager的 3 格范围内击杀了minecraft:villager,则不会生成战利品.若在 3 格范围之外击杀 minecraft:villager,则会生成相应的战利品

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:villager")
        .distanceToKiller(3)
        .addLoot("minecraft:diamond");
});

任意阶段检查

hasAnyStage(...stages)

hasAnyStage()语句传入的参数为玩家的阶段

若玩家持有指定的该阶段,则会对对应的生物/方块/战利品列表添加对应的战利品掉落

该方法建议搭配Game Stage [游戏阶段]模组进行搭配使用

下面的示例代码中,当玩家持有diamondSpawn阶段的时候,击杀minecraft:pig会生成钻石战利品掉落物

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:pig")
        .hasAnyStage("diamondsSpawn")
        .addLoot("minecraft:diamond");
});

玩家谓词

playerPredicate(callback)

谓词跳转Predicate.md 进行详情

下面的示例代码中,使用回调函数来检查player的血量是否大于 5,若大于 5 则生成对应的战利品,反之不生成战利品

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:pig")
        .playerPredicate((player) => player.getHealth() > 5)
        .addLoot("minecraft:emerald");
});

实体谓词

entityPredicate(callback)

谓词跳转Predicate.md 进行详情

下面的示例中,用回调函数来检查被击杀的minecraft:pig(Entity)是否处于水中,若处于水中则生成对应的战利品,反之则不生成战利品

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:pig")
        .entityPredicate((entity) => entity.isInWater())
        .addLoot("minecraft:emerald");
});

击杀者谓词

killerPredicate(callback)

谓词跳转Predicate.md 进行详情

上面已经科普过直接击杀者与间接击杀者的关系,下面的示例代码中,回调函数检测的是间接击杀者的谓词

当玩家手持钻石剑在水中杀死minecraft:pig的时候,会掉落一根羽毛,若玩家使用弓箭来杀死minecraft:pig,箭矢射到了水中,而玩家没处于水中,则不会生成战利品掉落,只有玩家在水中用弓箭(箭矢可以离开水面)射死minecraft:pig后才会掉落羽毛

这里可以很明显的看出,killerPredicate()语句是用于检测间接击杀者的谓词

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:pig")
        .killerPredicate((entity) => entity.isInWater())
        .addLoot("minecraft:feather");
});

直接击杀者谓词

directKillerPredicate(callback)

directKillerPredicate()的回调函数,是检测直接击杀者的谓词

例如:玩家射箭击杀了僵尸,检测的是箭而不是玩家,因为是箭对僵尸造成的击杀,并不是玩家对僵尸造成了击杀

下面的示例代码中,只有直接击杀者在水中击杀了minecraft:zombie后才会生成对应的战利品掉落物,例如:

  • 玩家在水中使用剑击杀了minecraft:zombie
  • 玩家射出的箭在水中击杀了minecraft:zombie
  • 玩家抛出的治疗药水在水中击杀了minecraft:zombie
js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:zombie")
        .killerPredicate((entity) => entity.isInWater())
        .addLoot("minecraft:feather");
});

not 语句

not(callback)

not()语句为 LootTable 的修改添加了一个否定,当不满足条件的时候生成对应的战利品

下面的示例代码中:not()语句回调函数检测玩家手上的物品是否为minecraft:diamond_sword,若为该物品,则不会生成战利品,反之则生成战利品

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .not((n) => {
            n.matchMainHand("minecraft:diamond_sword");
        })
        .addLoot("minecraft:diamond");
});

or 语句

or(callback)

or()语句为 LootTable 的修改添加多个条件,只要其中一个条件为真,则会对战利品进行修改,若一个条件都不为真,则不会进行战利品修改

下面的示例代码中,添加了两个条件,一个是检测玩家的主手是否为minecraft:diamond_sword,一个是检测玩家的副手是否为minecraft:coal,当玩家只要满足其中一个条件的时候,都会进行对战利品的修改

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .or((or) => {
            or.matchMainHand("minecraft:diamond_sword");
            or.matchOffHand("minecraft:coal");
        })
        .addLoot("minecraft:diamond");
});

and 语句

and(callback)

相较于上述的or()语句,and()语句则是必须满足所有条件,才会对战利品进行修改

下面的示例代码中,只有当玩家的主手为minecraft:diamond_sword以及副手为minecraft:coal的时候,战利品的修改才会生效.若缺少其中之一一个条件,战利品修改都不会生效

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .and((and) => {
            and.matchMainHand("minecraft:diamond_sword");
            and.matchOffHand("minecraft:coal");
        })
        .addLoot("minecraft:diamond");
});

自定义条件

customCondition(json)

customCondition()语句里要填入的参数为 json,当满足这个自定义条件的时候,对战利品进行修改,反之不会进行修改

下面的示例代码中,只有当对应修改的方块/实体在满足了minecraft:weather_checkrainingtrue的时候才会进行对其战利品的修改,也就是检查天气为雨天的时候才会对minecraft:creeper的战利品进行修改

具体更多的原版 JSON 可以查看Predicate.md 进行详情

js
LootJS.modifiers((event) => {
    event
        .addEntityLootModifier("minecraft:creeper")
        .customCondition({
            condition: "minecraft:weather_check",
            raining: true,
        })
        .addLoot("minecraft:diamond");
});

贡献者

页面历史