本篇教程的视频:

本篇教程源代码

GitHub地址:

介绍

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

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

无工具型战利品列表

查找源文件

写战利品列表其实并不需要写代码,只需要写json文件就可以了

不过后面我们使用数据生成的方式来生成战利品列表的时候,就可能需要用到一些代码

这里我们来查看Minecraft中的战利品列表的源文件,战利品列表属于数据文件,它的路径为data/minecraft/loot_table

我们再找到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上查看

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

1
2
3
4
5
6
7
8
9
10
public boolean test(final LootContext context) {
Float explosionRadius = context.getOptionalParameter(LootContextParams.EXPLOSION_RADIUS);
if (explosionRadius != null) {
RandomSource random = context.getRandom();
float probability = 1.0F / explosionRadius;
return random.nextFloat() <= probability;
} else {
return true;
}
}

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

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

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

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

创建战利品列表

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

首先我们在resources/data/tutorial/loot_table/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
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "tutorial:ice_ether_block"
}
],
"rolls": 1.0
}
]
}

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
{
"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": "tutorial: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": "tutorial:raw_ice_ether"
}
]
}
],
"rolls": 1.0
}
]
}

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

测试

我们现在进入游戏,因为前面我们在注册ice ether ore时加上了requiresCorrectToolForDrops,所以当我们挖这个矿石时,会发现它挖得很慢,破坏后也没有掉落物

而这部分内容就是我们接下去要讲的,需要特定工具才能开采的方块的战利品列表

有工具型战利品列表

介绍

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

我们已经写好的战利品列表本身没有问题,有工具的战利品列表和上面的是一样的,但得多写几个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这个方法,徒手也可以挖,只是有工具会更快)

总结一下:

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

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

创建tag

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

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

1
2
3
4
5
6
{
"values": [
"tutorial:raw_ice_ether_block",
"tutorial:ice_ether_ore"
]
}

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

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

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

测试

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