本篇教程的视频

本篇教程的源代码

GitHub地址:TutorialMod-Tags-1.20.1

本篇教程目标

  • 理解原版Tag标签)的注册,json文件格式
  • 学会Tag的注册和使用,利用数据生成生成Tagjson文件

简述

Tag标签,这是在游戏中用来给物品方块实体等东西来进行分类

当然,在我们之前写战利品列表的时候,已经接触过Tag了,这里的话我们再详细地来讲一下

我们可以使用Tag来编写配方、战利品列表等数据文件,也可以方便地进行一些方法的判断,
如判断某一些特定的矿石,你要用or||)来写的话,得写一堆,但如果用Tag来写的话,一句话就够了

上面这个例子可参见旧教程

探矿器旧教程:探矿器

Tag旧教程:Tag

本系列教程中移除了探矿器这个案例,因为相对而言,这个例子已经很详细了(1.21的比1.20的要更详细)

查看源代码

注意,本期教程只涉及物品方块的标签Tag,即ItemTagBlockTag
其他类型的标签我们将会在未来的教程中逐步涉及

常规操作,我们先来看源代码

源代码的话,只要看ItemTags或者BlockTags其中一个类就可以了,因为两个类差不多

ItemTags

1
2
3
4
5
public static final TagKey<Item> WOOL = of("wool");
...
private static TagKey<Item> of(String id) {
return TagKey.of(RegistryKeys.ITEM, new Identifier(id));
}

这是ItemTags类中其中一个注册语句和它的注册方法

这里注册的是WOOL标签,也就是羊毛,它的类型是TagKey<Item>

注册方法调用的是TagKey.of方法,传入两个参数,第一个是RegistryKeys.ITEM,也就是注册表项
第二个是Identifier,当然我们自己写是要加我们模组的ID

这里我们顺便来看看它对应的json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"values": [
"minecraft:white_wool",
"minecraft:orange_wool",
"minecraft:magenta_wool",
"minecraft:light_blue_wool",
"minecraft:yellow_wool",
"minecraft:lime_wool",
"minecraft:pink_wool",
"minecraft:gray_wool",
"minecraft:light_gray_wool",
"minecraft:cyan_wool",
"minecraft:purple_wool",
"minecraft:blue_wool",
"minecraft:brown_wool",
"minecraft:green_wool",
"minecraft:red_wool",
"minecraft:black_wool"
]
}

这是原版的wool标签对应的json文件,可以看到,它里面存放了原版所有颜色的羊毛

那么再找一个用到它的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"type": "minecraft:crafting_shaped",
"category": "misc",
"key": {
"#": {
"item": "minecraft:stick"
},
"X": {
"tag": "minecraft:wool"
}
},
"pattern": [
"###",
"#X#",
"###"
],
"result": {
"item": "minecraft:painting"
},
"show_notification": true
}

这是原版画对应的配方,可以看到,它里面用到了wool标签

原版其实有不少配方都用到了Tag,也有很多类中的方法也用到了Tag

BlockTags

BlockTags这里就不详细解释了,我们就看一下它的源代码

1
2
3
4
5
public static final TagKey<Block> WOOL = of("wool");
...
private static TagKey<Block> of(String id) {
return TagKey.of(RegistryKeys.BLOCK, new Identifier(id));
}

可以看到,BlockTagsItemTags差不多,只是TagKey使用的泛型注册表项不同

注册Tag

ModItemTags

接下来我们就来写自己的Tag,这里先来写物品的标签

创建ModItemTags

1
2
3
public class ModItemTags {

}

再写上注册方法,注册方法可以直接拿原版的,然后把命名空间改写一下

1
2
3
private static TagKey<Item> of(String id) {
return TagKey.of(RegistryKeys.ITEM, new Identifier(TutorialMod.MOD_ID, id));
}

最后我们就可以写我们自己的标签

1
public static final TagKey<Item> SUGAR_INGREDIENTS = of("sugar_ingredients");

这里注册了一个糖的原料物品标签,我们可以在后面的配方中使用它

ModBlockTags

相应的,方块的标签也差不多,也创建一个ModBlockTags

1
2
3
4
5
6
7
public class ModBlockTags {
public static final TagKey<Block> ETHER_BLOCK = of("ether_block");

private static TagKey<Block> of(String id) {
return TagKey.of(RegistryKeys.BLOCK, new Identifier(TutorialMod.MOD_ID, id));
}
}

这里注册一个ETHER_BLOCK的标签

数据生成

ItemTags

接下来我们就来生成我们的Tagjson文件,这里我们用数据生成来生成

前面我们创建过ModItemTagsProvider

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ModItemTagsProvider extends FabricTagProvider.ItemTagProvider {
public ModItemTagsProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> completableFuture) {
super(output, completableFuture);
}

@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {
getOrCreateTagBuilder(ModItemTags.SUGAR_INGREDIENTS)
.add(ModItems.CHEESE)
.add(ModItems.STRAWBERRY)
.add(Items.BEETROOT);
}
}

我们在重写的configure方法中,使用getOrCreateTagBuilder方法来将物品放到这个Tag

这里就放了模组的CHEESESTRAWBERRY和原版的BEETROOT

BlockTags

方块的标签前面写战利品列表的时候其实已经写过了,不过我们还是举个例子吧

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
public class ModBlockTagsProvider extends FabricTagProvider.BlockTagProvider {
public ModBlockTagsProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
super(output, registriesFuture);
}

@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {
getOrCreateTagBuilder(BlockTags.PICKAXE_MINEABLE)
.add(ModBlocks.ICE_ETHER_BLOCK)
.add(ModBlocks.ICE_ETHER_ORE);

getOrCreateTagBuilder(BlockTags.NEEDS_IRON_TOOL)
.add(ModBlocks.ICE_ETHER_ORE);

getOrCreateTagBuilder(ModBlockTags.ETHER_BLOCK)
.add(ModBlocks.ICE_ETHER_BLOCK)
.add(ModBlocks.RAW_ICE_ETHER_BLOCK)
.forceAddTag(BlockTags.COAL_ORES)
.forceAddTag(BlockTags.DIAMOND_ORES)
.forceAddTag(BlockTags.EMERALD_ORES)
.forceAddTag(BlockTags.GOLD_ORES)
.forceAddTag(BlockTags.IRON_ORES)
.forceAddTag(BlockTags.LAPIS_ORES)
.forceAddTag(BlockTags.REDSTONE_ORES);
}
}

我们把原版的矿石都加入到了ETHER_BLOCK标签中,这个其实就是旧教程中,应用到探矿器上的例子

forceAddTag方法可以添加现有的标签

使用Tag

使用配方中使用Tag的例子吧,我们就用糖的原料那个标签来写吧

1
2
3
4
5
ShapedRecipeJsonBuilder.create(RecipeCategory.FOOD, Items.SUGAR, 3)
.pattern("###")
.input('#', ModItemTags.SUGAR_INGREDIENTS)
.criterion(hasItem(Items.BEETROOT), conditionsFromTag(ModItemTags.SUGAR_INGREDIENTS))
.offerTo(exporter, new Identifier(TutorialMod.MOD_ID, "sugar_from_beetroot"));

这里我们将input中的输入物品改成了我们自己写的SUGAR_INGREDIENTS标签,这样我们的模组中的CHEESESTRAWBERRY和原版的BEETROOT都可以合成糖了

另外,在criterion中,我们也可以将第二个参数改为conditionsFromTag方法,这样就可以使用Tag中的物品作为条件了

第一个参数就不用改它,因为它本身就是一个字符串,这个在前面的数据生成那期教程就讲过了

然后我们就可以跑数据生成来看看生成的文件

1
2
3
4
5
6
7
8
{
"replace": false,
"values": [
"tutorial-mod:cheese",
"tutorial-mod:strawberry",
"minecraft:beetroot"
]
}

这个是sugar_ingredients.json文件的内容,可以看到,我们写的三个物品都成功添加进去了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"replace": false,
"values": [
"tutorial-mod:ice_ether_block",
"tutorial-mod:raw_ice_ether_block",
"#minecraft:coal_ores",
"#minecraft:diamond_ores",
"#minecraft:emerald_ores",
"#minecraft:gold_ores",
"#minecraft:iron_ores",
"#minecraft:lapis_ores",
"#minecraft:redstone_ores"
]
}

这个是ether_block.json文件的内容,现有标签会在前面加个#来与一般物品方块区分开来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"type": "minecraft:crafting_shaped",
"category": "misc",
"key": {
"#": {
"tag": "tutorial-mod:sugar_ingredients"
}
},
"pattern": [
"###"
],
"result": {
"count": 3,
"item": "minecraft:sugar"
},
"show_notification": true
}

这个是我们刚才改的配方文件,可以看到这里的key已经变成了Tag

测试

那么接下来我们就可以启动我们的游戏去测试了