标签

标签

标签是游戏对象的通用集合,用于将相关对象分组并快速检查成员资格。

标签合并示意:既有 A、B 集合,replace false 加入 C 后为 A、B、C;replace true 用 C 替换为 C;Forge remove 指定 B 后留下 A。

原创说明图,依据 Forge 1.21.x 官方文档 绘制。

查找标签

原版标签在 net.minecraft.tags 包中声明,例如 BlockTags 包含所有原版方块标签,BiomeTags 包含所有原版生物群系标签。

Forge 附带对 Mod 有用的额外标签,包括 Forge 专属标签和各主要 Mod 加载器通用的事实标准标签,均位于 net.minecraftforge.common.Tags。字段的方法名称和代码注释分组应能说明标签是 Forge 专属还是通用的。

警告:Forge 中 c 命名空间的通用标签跨加载器通用,但其他加载器可能在同一命名空间下有额外的专属标签。制作多加载器 Mod 时,如果考虑使用在其他加载器看到但 Forge 缺少的 c 标签,建议检查各加载器的标签以确保兼容。加载器专属的 c 标签在成为所有加载器的通用标签前,可能位于 Forge 的 forge 命名空间。

Forge 在原版之外添加的标签完整列表见此处。

声明自己的分组

标签在 Mod 的数据包中声明。例如标识符为 modid:foo/tagname 的 TagKey<Block> 指向 /data/<modid>/tags/blocks/foo/tagname.json。Block、Item、EntityType、Fluid 和 GameEvent 的文件夹名称使用复数,其他注册表使用单数,例如 EntityType 使用 entity_types,Potion 使用 potion。

同样,可以通过自己的 JSON 向其他域(例如原版)声明的标签追加内容或覆盖它们。例如将 Mod 树苗加入原版树苗标签,可在 /data/minecraft/tags/blocks/saplings.json 中指定。replace 为 false 时,原版在重载时合并内容;为 true 时,会移除该 JSON 之前的全部条目。列出的值不存在时会导致标签报错,除非使用 id 字符串和设为 false 的 required 布尔值,例如:

{
  "replace": false,
  "values": [
    "minecraft:gold_ingot",
    "mymod:my_ingot",
    { "id": "othermod:ingot_other", "required": false }
  ]
}

基础语法参见原版 Wiki。Forge 还扩展了原版语法:可以声明与 values 数组格式相同的 remove 数组,其中列出的值会从标签移除。这相当于更细粒度的 replace。

在代码中使用标签

所有注册表的标签都会在登录和重载时自动从服务端发送给远程客户端。Block、Item、EntityType、Fluid 和 GameEvent 有特殊处理,因为它们具有 Holder,可通过对象本身访问可用标签。

注意:侵入式 Holder 可能在 Minecraft 未来版本中移除。如果移除,可使用以下方法查询关联的 Holder。

ITagManager

Forge 包装的注册表通过 ITagManager 提供创建和管理标签的辅助功能,可通过 IForgeRegistry#tags 获取。使用 #createTagKey 或 #createOptionalTagKey 创建标签;分别通过 #getTag 或 #getReverseTag 查询标签或注册对象。

自定义注册表可在构造 DeferredRegister 时使用 #createTagKey 或 #createOptionalTagKey 创建标签,然后通过 DeferredRegister#makeRegistry 获取的 IForgeRegistry 查询标签或注册对象。

引用标签

有四种创建标签包装器的方法:

方法 用途
*Tags#create BannerPattern、Biome、Block、CatVariant、DamageType、EntityType、FlatLevelGeneratorPreset、Fluid、GameEvent、Instrument、Item、PaintingVariant、PoiType、Structure、WorldPreset;* 表示其中一种类型。
ITagManager#createTagKey Forge 包装的原版注册表,可从 ForgeRegistries 获取。
DeferredRegister#createTagKey 自定义 Forge 注册表。
TagKey#create 没有 Forge 包装的原版注册表,可从 Registry 获取。

注册对象可以分别通过 Holder 或 ITag / IReverseTag 检查原版或 Forge 注册对象的标签。原版注册对象可使用 Registry#getHolder 或 Registry#getHolderOrThrow 获取 holder,再用 Holder#is 检查标签。Forge 注册对象可使用 ITagManager#getTag 或 #getReverseTag 获取标签定义,分别使用 ITag#contains 或 IReverseTag#containsTag 检查。持有标签的注册对象在对象本身或感知状态的类中提供 #is,用于检查其是否属于某标签。

public static final TagKey<Item> myItemTag = ItemTags.create(ResourceLocation.fromNamespaceAndPath("mymod", "myitemgroup"));
public static final TagKey<Potion> myPotionTag = ForgeRegistries.POTIONS.tags().createTagKey(ResourceLocation.fromNamespaceAndPath("mymod", "mypotiongroup"));
public static final TagKey<VillagerType> myVillagerTypeTag = TagKey.create(Registries.VILLAGER_TYPE, ResourceLocation.fromNamespaceAndPath("mymod", "myvillagertypegroup"));

// 在某个方法中:
ItemStack stack = /*...*/;
boolean isInItemGroup = stack.is(myItemTag);
Potion potion = /*...*/;
boolean isInPotionGroup = ForgeRegistries.POTIONS.tags().getTag(myPotionTag).contains(potion);
ResourceKey<VillagerType> villagerTypeKey = /*...*/;
boolean isInVillagerTypeGroup = BuiltInRegistries.VILLAGER_TYPE.getHolder(villagerTypeKey).map(holder -> holder.is(myVillagerTypeTag)).orElse(false);

约定

  • 如果有适合方块或物品的原版标签,应将其加入。参见原版标签列表。
  • 如果有适合的 Forge 标签,应将其加入。Forge 声明的标签列表见 GitHub(原文链接指向 1.19.x)。
  • 如果认为某个分组应由社区共享,使用 forge 命名空间而不是 Mod ID。
  • 标签命名应遵循原版约定,特别是物品和方块分组使用复数,例如 minecraft:logs、minecraft:saplings。
  • 物品标签应按类型分到子目录,例如 forge:ingots/iron、forge:nuggets/brass。

从 OreDictionary 迁移

  • 配方可直接在原版格式中使用标签,见下文。
  • 在代码中匹配物品参见上文。
  • 声明新的物品分组时,使用 domain:type/material。所有 Mod 开发者都应采用的通用名称使用 forge 域。例如黄铜锭应注册在 forge:ingots/brass,钴粒应注册在 forge:nuggets/cobalt。

在配方和进度中使用标签

原版直接支持标签。使用详情分别参见原版 配方和进度文档。

原文:Tags。