Bedrock Creative Tabs

Quick rating

Community listing page, reviews here may not be monitored by the author.

Bedrock Creative Tabs

No reviews yet

Configurable bedrock style creative tabs

Mod Loaders
Minecraft

About

Description

Bedrock Creative Tabs

Configurable creative tabs for NeoForge: a resource pack names a set of item stacks and the tabs they belong to, and each of those tabs shows them as one icon that opens where it stands — the way Bedrock Edition groups its creative inventory. Nothing about which stacks fold, or where, is written in code.

This is a client-side mod. But for stability, it's recommended to install this mod on dedicated servers.

Resource pack

One JSON file per group, at assets/<namespace>/bedrock_creative_tabs/creative_group/<path>.json:

{
  "creative_tabs": [
    "minecraft:ingredients"
  ],
  "icon": {
    "id": "minecraft:red_dye"
  },
  "entries": [
    "#c:dyes"
  ],
  "priority": 0
}

A definition is reloaded with F3+T (or by switching packs). Reloading also rebuilds the tabs, so a change shows up as soon as the reload finishes.

Field Type Notes
entries List<Entry> Required, at least one. The stacks the group claims; any one entry matching is a match. A single entry may be written without the list.
icon Item Stack Optional. What the closed icon draws. Defaults to the first member the fold found on that tab.
creative_tabs List of Tab IDs Required, at least one. The tabs this group folds in. minecraft:search is refused.
priority Int Optional, defaults to 0. When two groups claim the same stack, the higher priority wins; a tie falls back to load order.

Also don't forget to translate your group's name with creative_group.<namespace>.<path> language keys.

Entries

An entry says one thing: whether it claims a stack. Five types ship with the mod.

Form Meaning
"minecraft:oak_planks" That item, by id.
"#minecraft:planks" Every item in that tag.
{ "type": "bedrock_creative_tabs:item", "id": "minecraft:oak_planks" } The same, written out.
{ "type": "bedrock_creative_tabs:item_tag", "tag": "minecraft:planks" } The same, written out.
{ "type": "bedrock_creative_tabs:block_tag", "tag": "minecraft:mineable/pickaxe" } Every item that places a block in that block tag.
{ "type": "bedrock_creative_tabs:has_component", "component": "minecraft:enchantments" } Every stack that carries that component, whatever its item.
{ "type": "bedrock_creative_tabs:regex", "pattern": "minecraft:.*_concrete" } Every item whose full id matches a regular expression.

You do not have to catch that by eye: every entry that matches no item at all is logged, naming the group and the entry.

WARN  Creative group bedrock_creative_tabs:planks: entry #c:planks matches no item

If an entry fails to parse — most often because it names a type that no installed mod provides, or because the type was written without its namespace — that entry is dropped with a warning in the log and the rest of the definition still loads; a group left with no entries at all is refused while it loads, so a broken group is never silently an empty one.

Adding an entry type

An entry type is a MapCodec registered under bedrock_creative_tabs:group_entry_type:

public final class MyEntryTypes {
    public static final DeferredRegister<MapCodec<? extends GroupEntry>> REGISTRY = DeferredRegister.create(BctRegistries.GROUP_ENTRY_TYPE, "mymod");

    public static final DeferredHolder<MapCodec<? extends GroupEntry>, MapCodec<RegexEntry>> REGEX = REGISTRY.register("regex", () -> RegexEntry.CODEC);
}

public record RegexEntry(Pattern pattern) implements GroupEntry {
    public static final MapCodec<RegexEntry> CODEC = Codec.STRING.comapFlatMap(RegexEntry::parse, entry -> entry.pattern.pattern()).fieldOf("pattern");

    @Override
    public boolean matches(ItemStack stack) {
        // The full id, namespace included: writing that into the pattern is what a pack does to narrow it.
        return this.pattern.matcher(BuiltInRegistries.ITEM.getKey(stack.getItem()).toString()).matches();
    }

    @Override
    public MapCodec<RegexEntry> codec() {
        return CODEC;
    }
}