Tags and creative tabs
Tags
A tag groups entries of one registry under a name such as #minecraft:mineable/pickaxe. The tag API is in dev.polymodloader.api.tag.
static final TagKey WARDED = TagKey.block(ResourceId.of("my_mod", "warded"));
static final TagKey SPARKLY = TagKey.item(ResourceId.of("my_mod", "sparkly"));
static final TagKey PICKAXE_MINEABLE = TagKey.block(ResourceId.minecraft("mineable/pickaxe"));
static final TagKey SKELETONS = TagKey.entityType(ResourceId.minecraft("skeletons"));
- A
TagKeyis only a name: aTagRegistry(BLOCK,ITEM,ENTITY_TYPE) and an ID without the#. Create keys once and keep them in constants. - The entries come from data packs and mod jars (
data/<namespace>/tags/<block|item|entity_type>/<path>.json) and fromaddToTag. They change on/reload. - Block, item, and entity type tags are supported.
Querying tags
world.isBlockIn(pos, WARDED); // the block at a position
player.mainHandStack().isIn(SPARKLY); // an item stack (ItemStackRef)
entity.isIn(SKELETONS); // an entity's type
world.tags().contains(SPARKLY, ResourceId.of("my_mod", "spark")); // any entry
world.tags().entries(SPARKLY); // every entry
| Method | Meaning |
|---|---|
WorldView.tags() | A TagView for the tags this world's side loaded |
TagView.contains(tag, entry) | Whether a block, item, or entity type ID is in the tag, nested tags included |
TagView.entries(tag) | Every entry of the tag, nested tags resolved, in the game's order. Empty for an unknown tag |
WorldView.isBlockIn(pos, tag) | Whether the block at pos is in a block tag |
ItemStackRef.isIn(tag) | Whether the stack's item is in an item tag |
EntityView.isIn(tag) | Whether the entity's type is in an entity type tag |
- The server reads the tags from its data packs. The client reads the copy the server sent.
- An unknown tag or entry is simply "not contained".
- A tag of the wrong kind, such as an item tag for a block position, throws
IllegalArgumentException. - Use a
TagViewon the thread of the world that handed it out, once a world is loaded. Results change after/reload, so do not cache them across reloads.
Adding entries from code
mod.content().addToTag(WARDED, ResourceId.of("my_mod", "warded_block"));
mod.content().addToTag(SPARKLY, ResourceId.of("my_mod", "spark"), ResourceId.of("my_mod", "glow_block"));
mod.content().addToTag(PICKAXE_MINEABLE, ResourceId.of("my_mod", "warded_block")); // a game tag
- Call
addToTagin the common entrypoint, like other declarations. After registration closes it throwsIllegalStateException(POLY-CONTENT-002). With no entries it throwsIllegalArgumentException. - It works like a tag file with
"replace": falsein the mod jar. Poly Mod Loader writes the entries to its generated data pack (.poly/generated-pack). The tag can be in any namespace. Several calls and several mods add up, and tag files from the mod jar still apply. - Entries are written as optional entries and checked when the registries freeze. An entry that is not registered then is reported with
POLY-CONTENT-007and left out. The rest of the tag still loads.
Creative tabs
The game's tabs
To list an item at the end of one of the game's tabs, use creativeTab(CreativeTab.…) in its item definition. The tabs are listed in Blocks.
A mod's own tab
ContentHandle tab = mod.content().creativeTab("showcase", CreativeTabDefinition.builder()
.icon(ResourceId.of("my_mod", "glow_block")) // without an icon: the first entry
.entries(ResourceId.of("my_mod", "glow_block"), ResourceId.of("my_mod", "spark"))
.entry(ResourceId.minecraft("amethyst_shard")) // the game's items work too
.build());
assets/my_mod/lang/en_us.json
{"itemGroup.my_mod.showcase": "My Mod"}
creativeTab(path, definition)declares the tab<mod id>:<path>in the common entrypoint. Its title is the translation ofitemGroup.<mod id>.<path>.CreativeTabDefinition.builder()takes an optionalicon(item)and the entries in order (entry,entries). Entries can be mod items or the game's items.build()throwsIllegalArgumentExceptionif no entry was added.- An invalid or already used path throws
IllegalArgumentException(POLY-CONTENT-001). After registration closes,IllegalStateException(POLY-CONTENT-002). - Entries and the icon are checked when the registries freeze. One that is not a registered item then is reported with
POLY-CONTENT-008and left out. A missing icon falls back to the first valid entry. A tab left with no entries is not registered. - The tab's items also appear in the creative search tab.
Pages
The game's creative screen has room for 14 tabs, and the game uses all of them. So Poly Mod Loader puts mod tabs on extra pages:
- Mod tabs go on pages 1, 2, … in declaration order, ten per page (the left five slots of the top and bottom rows).
- The game's right-hand tabs (saved hotbars, search, operator items, inventory) are shown on every page.
- When mod tabs exist,
<and>buttons appear above the tab row. Turning the page selects the first tab of that page.
What is verified
Registration and the per-page position check run on the game test server. The client-side transform rules and hooks are checked by unit tests against the real 26.2 classes. How the paged screen looks (button placement, tab drawing) has not been checked by a person yet, because no window-opening test was run.