The Best Resource for Minecraft
The Best Resource for Minecraft

Resources: Tags

Chapter 46 of 70 · 1,154 words
← All chapters

Tags

Tags are generalized sets of objects in the game used for grouping related things together and providing fast membership checks.

Finding Tags

When looking for existing tags, there’s two main places to check:

Vanilla Tags

Vanilla tags are declared in the net.minecraft.tags package. For example, BlockTags contains all the Vanilla block tags, BiomeTags contains all the Vanilla biome tags, and so on.

Forge Tags

Forge bundles additional tags useful for mods, both Forge-specific and de-facto common tags that apply across all major mod loaders. You can find all of them in the net.minecraftforge.common.Tags class. The method names for each of the fields as well as code comment groups should make it clear which is a Forge-specific tag and which is a common tag.

Warning

The common c namespaced tags seen in Forge are common across all loaders, however other loaders may have additional loader-specific tags under the same c namespace. When making a multi-loader mod, it is recommended to check the tags for each loader to ensure compatibility if you are considering a c tag you saw on other loaders that is missing in Forge. Loader-specific c tags may be in Forge under the forge namespace until they become common across all loaders.

Full list of tags in Forge

You can find a full list of tags Forge adds on top of Vanilla Minecraft here.

Declaring Your Own Groupings

Tags are declared in your mod’s datapack. For example, a TagKey<Block> with a given identifier of modid:foo/tagname will reference a tag at /data/<modid>/tags/blocks/foo/tagname.json. Tags for Blocks, Items, EntityTypes, Fluids, and GameEvents use the plural forms for their folder location while all other registries use the singular version (EntityType uses the folder entity_types while Potion would use the folder potion). Similarly, you may append to or override tags declared in other domains, such as Vanilla, by declaring your own JSONs. For example, to add your own mod’s saplings to the Vanilla sapling tag, you would specify it in /data/minecraft/tags/blocks/saplings.json, and Vanilla will merge everything into one tag at reload, if the replace option is false. If replace is true, then all entries before the json specifying replace will be removed. Values listed that are not present will cause the tag to error unless the value is listed using an id string and required boolean set to false, as in the following example:

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

See the Vanilla wiki for a description of the base syntax.

There is also a Forge extension on the Vanilla syntax. You may declare a remove array of the same format as the values array. Any values listed here will be removed from the tag. This acts as a finer grained version of the Vanilla replace option.

Using Tags In Code

Tags for all registries are automatically sent from the server to any remote clients on login and reload. Blocks, Items, EntityTypes, Fluids, and GameEvents are special cased as they have Holders allowing for available tags to be accessible through the object itself.

Note

Intrusive Holders may be removed in a future version of Minecraft. If they are, the below methods can be used instead to query the associated Holders.

ITagManager

Forge wrapped registries provide an additional helper for creating and managing tags through ITagManager which can be obtained via IForgeRegistry#tags. Tags can be created using using #createTagKey or #createOptionalTagKey. Tags or registry objects can also be checked for either or using #getTag or #getReverseTag respectively.

Custom Registries

Custom registries can create tags when constructing their DeferredRegister via #createTagKey or #createOptionalTagKey respectively. Their tags or registry objects can then checked for either using the IForgeRegistry obtained by calling DeferredRegister#makeRegistry.

Referencing Tags

There are four methods of creating a tag wrapper:

Method For
*Tags#create BannerPattern, Biome, Block, CatVariant, DamageType, EntityType, FlatLevelGeneratorPreset, Fluid, GameEvent, Instrument, Item, PaintingVariant, PoiType, Structure, and WorldPreset where * represents one of these types.
ITagManager#createTagKey Forge wrapped vanilla registries, registries can be obtained from ForgeRegistries.
DeferredRegister#createTagKey Custom forge registries.
TagKey#create Vanilla registries without forge wrappers, registries can be obtained from Registry.

Registry objects can check their tags or registry objects either through their Holder or through ITag/IReverseTag for vanilla or forge registry objects respectively.

Vanilla registry objects can grab their associated holder using either Registry#getHolder or Registry#getHolderOrThrow and then compare if the registry object has a tag using Holder#is.

Forge registry objects can grab their tag definition using either ITagManager#getTag or ITagManager#getReverseTag and then compare if a registry object has a tag using ITag#contains or IReverseTag#containsTag respectively.

Tag-holding registry objects contain a method called #is in either their registry object or state-aware class to check whether the object belongs to a certain tag.

As an example:

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"));

// In some method:

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);

Conventions

There are several conventions that will help facilitate compatibility in the ecosystem:

  • If there is a Vanilla tag that fits your block or item, add it to that tag. See the list of Vanilla tags.
  • If there is a Forge tag that fits your block or item, add it to that tag. The list of tags declared by Forge can be seen on GitHub.
  • If there is a group of something you feel should be shared by the community, use the forge namespace instead of your mod id.
  • Tag naming conventions should follow Vanilla conventions. In particular, item and block groupings are plural instead of singular (e.g. minecraft:logs, minecraft:saplings).
  • Item tags should be sorted into subdirectories according to their type (e.g. forge:ingots/iron, forge:nuggets/brass, etc.).

Migration from OreDictionary

  • For recipes, tags can be used directly in the vanilla recipe format (see below).
  • For matching items in code, see the section above.
  • If you are declaring a new type of item grouping, follow a couple naming conventions:
  • Use domain:type/material. When the name is a common one that all modders should adopt, use the forge domain.
  • For example, brass ingots should be registered under the forge:ingots/brass tag and cobalt nuggets under the forge:nuggets/cobalt tag.

Using Tags in Recipes and Advancements

Tags are directly supported by Vanilla. See the respective Vanilla wiki pages for recipes and advancements for usage details.