本篇教程的视频:

本篇教程源代码

GitHub地址:TutorialMod-LootTable-1.21

无工具型战利品列表

介绍

战利品列表(Loot Table)是一种用于定义方块掉落物品的机制。在Minecraft中,方块掉落物品是通过战利品列表来定义的。

另外,战利品列表也可以用于定义实体掉落物品,但是这里我们只讲方块掉落物品。

查找源文件

写战利品列表其实并不需要写代码,只需要写json文件就可以了。
不过后面我们使用数据生成的方式来生成战利品列表的时候,就可能需要用到一些代码。

这里我们来查看Minecraft中的战利品列表的源文件,战利品列表属于数据文件,所以它的路径为data/minecraft/loot_tables
我们再找到blocks,以diamond_block.json为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:diamond_block"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/diamond_block"
}

战利品列表中的各个参数可以在Wiki上查看,这里只是简单地介绍一下

type是战利品列表的类型,用于检测当前的战利品列表是否满足其上下文参数,如果有问题则抛出错误

pools是随机池,由bonus_rollsrolls来决定抽取次数,其中bonus_rolls是玩家幸运值与钓鱼竿附魔等级(海之眷顾)之和,再乘上此字段所得到的额外抽取次数(海之眷顾的加成仅在钓鱼时生效)rolls是基本抽取次数

entries是掉落物品,type是掉落物品的类型,name是掉落物品的名称

conditions是掉落条件,只有满足条件的掉落物品才会掉落,这里代表爆炸时返回。minecraft:survives_explosion我们将其称为谓词,其他谓词可以在Wiki上查看

如果要进一步深入了解这些谓词,可以看源代码中的LootConditionTypes类,其中Wiki上给出的survives_explosion的计算逻辑,我们可在SurvivesExplosionLootCondition中找到

1
2
3
4
5
6
7
8
9
10
public boolean test(LootContext lootContext) {
Float float_ = lootContext.get(LootContextParameters.EXPLOSION_RADIUS);
if (float_ != null) {
Random random = lootContext.getRandom();
float f = 1.0F / float_;
return random.nextFloat() <= f;
} else {
return true;
}
}

也就是1/爆炸半径,另外LootContextParameters是战利品列表的上下文参数,也可自行了解

另外,tntExplosionDropDecay这个游戏规则也会影响爆炸导致的掉落物,默认为false,总是掉落,不受前面概率的影响

random_sequence是随机序列,用于生成随机数,这里我们不做介绍

PS:战利品列表的内容及其运作方式倘若要详细了解,还是推荐查看源代码(我自己也只是了解了点皮毛)

创建战利品列表

之前我们创建了三个方块,现在我们为这三个方块创建战利品列表

首先我们在resources/data/tutorialmod/loot_tables/blocks文件夹下创建三个json文件,分别为ice_ether_ore.jsonice_ether_block.jsonraw_ice_ether_block.json

ice_ether_block.json的内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "tutorialmod:ice_ether_block"
}
],
"rolls": 1.0
}
],
"random_sequence": "tutorialmod:blocks/ice_ether_block"
}

raw_ice_ether_block.json差不多,这里就不放了

不过,这里的ice_ether_ore.json我们照搬copper.json的内容,我们希望这个矿石那个像铜矿石一样,有多个掉落物品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"conditions": [
{
"condition": "minecraft:match_tool",
"predicate": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
}
],
"name": "tutorialmod:ice_ether_ore"
},
{
"type": "minecraft:item",
"functions": [
{
"add": false,
"count": {
"type": "minecraft:uniform",
"max": 5.0,
"min": 2.0
},
"function": "minecraft:set_count"
},
{
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops",
"function": "minecraft:apply_bonus"
},
{
"function": "minecraft:explosion_decay"
}
],
"name": "tutorialmod:ice_ether"
}
]
}
],
"rolls": 1.0
}
],
"random_sequence": "tutorialmod:blocks/ice_ether_ore"
}

这里我们可以看到它最多能掉落5个,最少2个,而且还有精准采集(Silk Touch)的附魔,一般矿石可以写个精准采集(当然了,数据生成是可以生成这一堆的)

测试

我们现在进入游戏,因为我之前也提到过暂时不要写requireTool,所以这里我们能徒手挖掉这三个方块,在文件名没有问题的情况下,我们就能看到掉落物品了

有工具型战利品列表

介绍

那么有工具型的战利品列表就是在有工具的情况下才能掉落物品,也就是之前注册方块时加上requireTool这个方法

当我们加上requireTool后,再挖上面的那些方块时,我们会发现挖起来很费劲,同时也没有产生掉落物

我们已经写好的战利品列表本身没有问题,有工具的战利品列表和上面的是一样的,但得多写几个Tag

我们翻看MC的tags时,在block中,我们可以发现一个mineable,显然易见,这是可挖掘的。在它的下面,分别有axe, hoe, pickaxe, shovel,这四个文件,分别代表斧、锄、镐、铲。而在这些文件中,写了很多的方块,这些方块就是需要这些工具才能挖掉的方块

而在mineable的外面,即block下,还有needs_stone_toolneeds_iron_toolneeds_diamond_tool,这三个文件,分别代表石头工具、铁工具、钻石工具。而在这些文件中同样写了很多的方块,这些方块就是需要这些对应等级的工具才能挖掉的方块

解释一下,比如说diamond_block,它既在mineable/pickaxe中,又在needs_iron_tool中,所以我们用铁镐才能挖掉它

而MC中的所有logs,它们都在mineable/axe中,但外面的那些文件中没有logs,所以我们用任意等级的斧头就能挖掉它们(当然,因为它们注册时没有写requireTool这个方法,徒手也可以挖,只是有工具会更快)

总结一下:

方块在注册时没有写requireTool这个方法,可以徒手挖掉,但是有工具也能挖掉,只是有工具会更快

方块在注册时写了requireTool这个方法,必须写mineable中的tag,否则挖掉无掉落物,错误工具也无掉落物;
如果有工具等级的要求(木制的也是不写),则还需再写needs_stone_toolneeds_iron_toolneeds_diamond_tool中的一个

创建tag

这里的教程我为之前注册的方块加上了requireTool这个方法,所以我们需要创建tag文件

我们先来写mineable/pickaxe.json注意!因为这是Minecraft的tag,所以我们的文件路径是resources/data/minecraft/tags/blocks/mineable/pickaxe.json

1
2
3
4
5
6
7
8
{
"replace": false,
"values": [
"tutorialmod:ice_ether_block",
"tutorialmod:ice_ether_ore",
"tutorialmod:raw_ice_ether_block"
]
}

另外,我们可以再设置方块的采集等级,比如说needs_stone_tool

1
2
3
4
5
{
"values": [
"tutorialmod:raw_ice_ether_block"
]
}

再写一个needs_iron_tool.json

1
2
3
4
5
{
"values": [
"tutorialmod:ice_ether_ore"
]
}

另外一个ice_ether_block我们就不写了,让它拿任意等级的镐都能挖掉

测试

我们现在进入游戏,用不同等级的镐去挖这些方块,我们会发现,有工具的情况下才会掉落物品,但错误等级的工具也不会掉落物品