Line 2: |
Line 2: |
| | | |
| == Declaring Your Own Groupings == | | == Declaring Your Own Groupings == |
− | Tags are declared in your mod’s [https://mcforge.readthedocs.io/en/latest/utilities/tags/datapacks.md datapack]. For example, <code><nowiki>/data/modid/tags/blocks/foo/tagname.json</nowiki></code> will declare a <code><nowiki>Tag$Named<Block></nowiki></code> with ID <code><nowiki>modid:foo/tagname</nowiki></code>. 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 <code><nowiki>/data/minecraft/tags/blocks/saplings.json</nowiki></code>, and Vanilla will merge everything into one tag at reload, if the <code><nowiki>replace</nowiki></code> option is false. If <code><nowiki>replace</nowiki></code> is true, then all entries before the json specifying <code><nowiki>replace</nowiki></code> will be removed. See the [https://minecraft.gamepedia.com/Tag#JSON_format Vanilla wiki] for a description of the base syntax. | + | Tags are declared in your mod’s [https://mcforge.readthedocs.io/en/latest/utilities/tags/datapacks.md datapack]. For example, a <code><nowiki>TagKey<Block></nowiki></code> with a given identifier of <code><nowiki>modid:foo/tagname</nowiki></code> will reference a tag at <code><nowiki>/data/<modid>/tags/blocks/foo/tagname.json</nowiki></code>. Tags for <code><nowiki>Block</nowiki></code>s, <code><nowiki>Item</nowiki></code>s, <code><nowiki>EntityType</nowiki></code>s, <code><nowiki>Fluid</nowiki></code>s, and <code><nowiki>GameEvent</nowiki></code>s use the plural forms for their folder location while all other registries use the singular version (<code><nowiki>EntityType</nowiki></code> uses the folder <code><nowiki>entity_types</nowiki></code> while <code><nowiki>Potion</nowiki></code> would use the folder <code><nowiki>potion</nowiki></code>). 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 <code><nowiki>/data/minecraft/tags/blocks/saplings.json</nowiki></code>, and Vanilla will merge everything into one tag at reload, if the <code><nowiki>replace</nowiki></code> option is false. If <code><nowiki>replace</nowiki></code> is true, then all entries before the json specifying <code><nowiki>replace</nowiki></code> will be removed. |
| | | |
− | Forge provides two extensions on the Vanilla syntax: * You may declare an <code><nowiki>optional</nowiki></code> array of the same format as the <code><nowiki>values</nowiki></code> array, but any values listed here that are not present will not cause the tag loading to error. This is useful to provide integration for mods that may or may not be present at runtime.
| + | Values listed that are not present will cause the tag to error unless the value is listed using an <code><nowiki>id</nowiki></code> string and <code><nowiki>required</nowiki></code> boolean set to false, as in the following example: |
− | * You may declare a <code><nowiki>remove</nowiki></code> array of the same format as the <code><nowiki>values</nowiki></code> array. Any values listed here will be removed from the tag. This acts as a finer grained version of the Vanilla <code><nowiki>replace</nowiki></code> option.
| + | |
| + | <syntaxhighlight lang="json"> |
| + | { |
| + | "replace": false, |
| + | "values": [ |
| + | "minecraft:gold_ingot", |
| + | "mymod:my_ingot", |
| + | { |
| + | "id": "othermod:ingot_other", |
| + | "required": false |
| + | } |
| + | ] |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | See the [https://minecraft.gamepedia.com/Tag#JSON_format Vanilla wiki] for a description of the base syntax. |
| + | |
| + | |
| + | There is also a Forge extension on the Vanilla syntax. |
| + | You may declare a <code><nowiki>remove</nowiki></code> array of the same format as the <code><nowiki>values</nowiki></code> array. Any values listed here will be removed from the tag. This acts as a finer grained version of the Vanilla <code><nowiki>replace</nowiki></code> option. |
| | | |
| ==Using Tags In Code== | | ==Using Tags In Code== |
− | Block, Item, and Fluid tags are automatically sent from the server to any remote clients on login and reload. Function tags are not synced.
| + | Tags for all registries are automatically sent from the server to any remote clients on login and reload. <code><nowiki>Block</nowiki></code>s, <code><nowiki>Item</nowiki></code>s, <code><nowiki>EntityType</nowiki></code>s, <code><nowiki>Fluid</nowiki></code>s, and <code><nowiki>GameEvent</nowiki></code>s are special cased as they have <code><nowiki>Holder</nowiki></code>s allowing for available tags to be accessible through the object itself. |
| | | |
− | <code><nowiki>BlockTags#getAllTags</nowiki></code> and <code><nowiki>ItemTags#getAllTags()</nowiki></code> will retrieve the current <code><nowiki>TagCollection</nowiki></code>, from which you can retrieve a <code><nowiki>Tag</nowiki></code> object by its ID. With a <code><nowiki>Tag</nowiki></code> object in hand, membership can be tested with <code><nowiki>tag.contains(thing)</nowiki></code>, or all the objects in the tag queried with <code><nowiki>tag.getAllElements()</nowiki></code>. | + | Tags wrappers can be created using <code><nowiki>TagKey#create</nowiki></code> where the registry the tag should belong to and the tag name are supplied. Some vanilla defined helpers are also available to create wrappers via <code><nowiki>*Tags#create</nowiki></code> where <code><nowiki>*</nowiki></code> refers to the name of the registry object. |
| + | |
| + | Forge wrapped registry objects can grab their associated holder using <code><nowiki>IForgeRegistry#getHolder</nowiki></code> while non-Forge registry objects use either <code><nowiki>Registry#getHolder</nowiki></code> or <code><nowiki>Registry#getHolderOrThrow</nowiki></code>. They then can compare if the registry object has a tag using <code><nowiki>Holder#is</nowiki></code>. Tag-holding registry objects contain a method called <code><nowiki>#is</nowiki></code> in either their registry object or state-aware class to check whether the object belongs to a certain tag. |
| | | |
| As an example: | | As an example: |
| <syntaxhighlight lang="java"> | | <syntaxhighlight lang="java"> |
− | public static final Tag.Named<Item> myTag = ItemTags.bind("mymod:myitemgroup"); | + | public static final TagKey<Item> myItemTag = ItemTags.create(new ResourceLocation("mymod", "myitemgroup")); |
| | | |
− | // In some method | + | public static final TagKey<Potion> myPotionTag = TagKey.create(Registry.POTION, new ResourceLocation("mymod", "mypotiongroup")); |
− | Item unknownItem = stack.getItem();
| + | |
− | boolean isInGroup = unknownItem.is(myTag); | + | public static final TagKey<VillagerType> myVillagerTypeTag = TagKey.create(Registry.VILLAGER_TYPE, new ResourceLocation("mymod", "myvillagertypegroup")); |
| + | |
| + | // In some method where stack is an ItemStack |
| + | boolean isInItemGroup = stack.is(myItemTag); |
| + | |
| + | // In some method where potionName is a ResourceLocation |
| + | boolean isInPotionGroup = ForgeRegistries.POTIONS.getHolder(potionName).map(holder -> holder.is(myPotionTag)).orElse(false); |
| + | |
| + | // In some method where villagerTypeKey is a ResourceKey<VillagerType> |
| + | boolean isInVillagerTypeGroup = Registry.VILLAGER_TYPE.getHolder(villagerTypeKey).map(holder -> holder.is(myVillagerTypeTag)).orElse(false); |
| </syntaxhighlight> | | </syntaxhighlight> |
− |
| |
− | {{Tip|The <code><nowiki>TagCollection</nowiki></code> returned by <code><nowiki>#getAllTags</nowiki></code> (and the <code><nowiki>Tag</nowiki></code>s within it) may expire if a reload happens, so you should always query the collection anew every time you need it. The static <code><nowiki>Tag$Named</nowiki></code> fields in <code><nowiki>BlockTags</nowiki></code> and <code><nowiki>ItemTags</nowiki></code> avoid this by introducing a wrapper that handles this expiring. Alternatively, a resource reload listener can be used to refresh any cached tags.}}
| |
| | | |
| == Migration from OreDictionary == | | == Migration from OreDictionary == |