本篇教程的视频

本篇教程的源代码

GitHub地址:TutorialMod-Tag-1.21

介绍

Tag是一种标签,用于方块、物品以及实体的分类。

具体可见Wiki

在Minecraft中,我们可以将具有相同或类似属性的方块、物品或实体放在一个Tag中,然后可以通过这个Tag进行一些逻辑处理,比如合成

比如说在游戏中,木板可以合成木棍,但是木板有很多种。如果为每一种木板都写一个配方,那就太麻烦了。游戏就使用Tag来简化配方的编写

同理,我们的前一篇教程中的Prospector探测的矿石也可以使用Tag来简化代码。将其能够探测的矿石放在一个Tag中,然后通过这个Tag来判断矿石

注册Tag

查看源代码

Minecraft的Tag有很多种,它的那些Tagnet.minecraft.registry.tag包下,本篇教程我们主要使用ItemTagsBlockTags

两者差不多,无非在于注册方法中的参数不同

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, Identifier.ofVanilla(id));
}
1
2
3
4
5
public static final TagKey<Item> PLANKS = of("planks");

private static TagKey<Item> of(String id) {
return TagKey.of(RegistryKeys.ITEM, Identifier.ofVanilla(id));
}

前者是方块的Tag,后者是物品的Tag,他们的不同之处就是TagKey的泛型参数和RegistryKeys的参数

而其具体在哪里使用这就自行研究了,这里不再赘述

创建ModBlockTags类

接下来我们创建一个ModBlockTags

1
2
3
public class ModBlockTags {

}

然后在这里面我们来注册我们的Tag

1
2
3
4
public static final TagKey<Block> ORE_LIST = of("ore_list");
private static TagKey<Block> of(String id) {
return TagKey.of(RegistryKeys.BLOCK, Identifier.of(TutorialMod.MOD_ID, id));
}

这个of方法其实就是原版的方法,但要记得将Identifier改一下

然后我们注册一个ORE_LISTTag,这个Tag是来改写我们的Prospector

另外,初始化注册方法也不要忘了

1
2
3
public static void registerModBlockTags() {
TutorialMod.LOGGER.info("Registering Block Tags");
}

以及主类中的调用

1
ModBlockTags.registerModBlockTags();

创建ModItemTags类

同理,我们创建一个ModItemTags

1
2
3
4
5
6
7
8
9
public class ModItemTags {
public static final TagKey<Item> SUGAR_TAG = of("sugar_tag");
private static TagKey<Item> of(String id) {
return TagKey.of(RegistryKeys.ITEM, Identifier.of(TutorialMod.MOD_ID, id));
}
public static void registerModItemTags() {
TutorialMod.LOGGER.info("Registering Item Tags");
}
}

其方法是和ModBlockTags一样的,这里我们注册一个SUGAR_TAGTag,其他的不再赘述

为Tag添加内容

手动添加Tag的内容是很麻烦的,方法的话在讲战利品列表的时候也讲过了。

我们这里使用DataGen来生成Tag的内容

BlockTagsProvider

我们在configure方法中添加以下内容

1
2
3
4
5
6
7
8
9
10
getOrCreateTagBuilder(ModBlockTags.ORE_LIST)
.add(ModBlocks.ICE_ETHER_ORE)
.forceAddTag(BlockTags.COAL_ORES)
.forceAddTag(BlockTags.IRON_ORES)
.forceAddTag(BlockTags.GOLD_ORES)
.forceAddTag(BlockTags.LAPIS_ORES)
.forceAddTag(BlockTags.REDSTONE_ORES)
.forceAddTag(BlockTags.DIAMOND_ORES)
.forceAddTag(BlockTags.EMERALD_ORES)
.forceAddTag(BlockTags.COPPER_ORES);

这里我们将ICE_ETHER_ORE放入了ORE_LIST中,然后将BlockTags中的矿石Tag(这些矿石的Tag包括普通矿石和深层矿石)放入了ORE_LIST

addforceAddTag的区别在于,add是添加单个方块或者物品;而forceAddTag是添加已有的Tag,他们接受的参数是不同的

ItemTagsProvider

同理,我们在configure方法中添加以下内容

1
2
3
4
getOrCreateTagBuilder(ModItemTags.SUGAR_TAG)
.add(Items.BEETROOT)
.add(ModItems.CHEESE)
.add(ModItems.STRAWBERRY);

这里我们将BEETROOTCHEESESTRAWBERRY放入了SUGAR_TAG

然后我们运行Data Generation,生成对应的json文件,而后我们就可以在generated中看到我们生成的Tag文件

比如ore_list.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"values": [
"tutorialmod:ice_ether_ore",
"#minecraft:coal_ores",
"#minecraft:iron_ores",
"#minecraft:gold_ores",
"#minecraft:lapis_ores",
"#minecraft:redstone_ores",
"#minecraft:diamond_ores",
"#minecraft:emerald_ores",
"#minecraft:copper_ores"
]
}

使用Tag

修改Prospector类

我们将isRightBlock方法修改为

1
2
3
private boolean isRightBlock(BlockState blockState) {
return blockState.isIn(ModBlockTags.ORE_LIST);
}

这里我们使用isIn方法来判断这个方块是不是在ORE_LIST中,其接受的参数是Tag,所以我们直接传入ORE_LIST即可

这样我们在探测矿石的时候就可以输出所有在ORE_LIST中的矿石了

配方

我们之前写了一个甜菜制糖的配方,我们可以将这个配方改为使用SUGAR_TAG来制作

1
2
3
4
5
ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, Items.SUGAR,3)
.pattern("###")
.input('#', ModItemTags.SUGAR_TAG)
.criterion("has_item", RecipeProvider.conditionsFromItem(Items.BEETROOT))
.offerTo(exporter, Identifier.of(TutorialMod.MOD_ID, "beetroot_to_sugar"));

我们将#的输入改为SUGAR_TAG,这样我们就可以使用BEETROOTCHEESESTRAWBERRY来制作糖了

这样我们就不用写一堆的配方了,只需要这一个配方就可以完成制糖