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");
});

Contributors

Changelog

Layout Switch

Adjust the layout style of VitePress to adapt to different reading needs and screens.

Expand all
The sidebar and content area occupy the entire width of the screen.
Expand sidebar with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Expand all with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Original width
The original layout width of VitePress

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.

Spotlight

Highlight the line where the mouse is currently hovering in the content to optimize for users who may have reading and focusing difficulties.

ONOn
Turn on Spotlight.
OFFOff
Turn off Spotlight.