Skip to content

Java API GroupDefinition

StarskyXIII edited this page Mar 25, 2026 · 1 revision

Java API: GroupDefinition

HomeJava API › GroupDefinition

This page explains the full GroupDefinition object, how display names work, how icons are configured, and how to move from simple examples to more advanced ones.


When to Read This Page

  • You already understand GroupFilter and are ready to create actual group objects
  • You want to see how id, display name, icon, and filter come together
  • You want Java examples you can copy and adapt

Quick Take

  • GroupDefinition is the complete Java-side group object
  • construction automatically runs normalization, validation, and compilation
  • the String name overload is convenient for quick setup; for formal built-in groups, GroupDisplayName.Localized is usually clearer

GroupDefinition: the full group object

GroupDefinition includes:

  • id
  • displayName
  • enabled
  • filter
  • iconIds

When you create a GroupDefinition, the mod automatically does three things:

  1. normalizes the filter
  2. validates the filter
  3. compiles compiledFilter

That means:

  • you do not need to manually shape the filter into its final form first
  • invalid filters fail early at construction time instead of failing silently later

Core Concept: display names

The authoritative name is not just a plain string. It is GroupDisplayName.

Important facts:

  • displayName() is the authoritative source
  • name() is only the resolved display text in the current language
  • the current implementation type is GroupDisplayName.Localized

What happens when you use the String overload

GroupDefinition currently includes overloads that accept String name, for example:

new GroupDefinition(
    "mypack:barrel",
    "Barrel",
    true,
    Filters.itemId("minecraft:barrel")
)

That does not simply store a string and stop there. Under the hood, it still becomes:

  • an auto-generated translation key based on the group ID
  • the string you passed in as the fallback name

So:

  • use the String overload when you want a quick, convenient definition
  • use new GroupDisplayName.Localized(key, fallback) when you want full control over the key and fallback

Explicit GroupDisplayName.Localized

GroupDefinition barrels = new GroupDefinition(
    "mypack:barrel",
    new GroupDisplayName.Localized(
        "group.collapsible_groups.mypack.barrel",
        "Barrel"
    ),
    true,
    Filters.itemId("minecraft:barrel")
);

This is usually the clearer form for formal built-in groups and long-term integrations.


Core Concept: iconIds

GroupDefinition supports an icon ID list, but it is optional.

iconIds tends to be useful when:

  • a group contains many entries and you want faster visual recognition
  • the group concept is abstract and the name alone is not enough
  • you are building formal built-in groups and want a more polished result

If you do not need icons, omit them. If you do, pass a List<String>.


Examples

Example 1: the simplest single-item group

GroupDefinition barrel = new GroupDefinition(
    "mypack:barrel",
    "Barrel",
    true,
    Filters.itemId("minecraft:barrel")
);

Example 2: OR group with multiple items

GroupDefinition utilityBlocks = new GroupDefinition(
    "mypack:utility_blocks",
    "Utility Blocks",
    true,
    Filters.any(
        Filters.itemId("minecraft:barrel"),
        Filters.itemId("minecraft:crafting_table"),
        Filters.itemId("minecraft:chest")
    )
);

Example 3: AND group with tag + namespace

GroupDefinition vanillaLogs = new GroupDefinition(
    "mypack:vanilla_logs",
    "Vanilla Logs",
    true,
    Filters.all(
        Filters.itemTag("minecraft:logs"),
        Filters.itemNamespace("minecraft")
    )
);

Example 4: exclusion group

GroupDefinition planksExceptOak = new GroupDefinition(
    "mypack:planks_except_oak",
    "Planks Except Oak",
    true,
    Filters.all(
        Filters.itemTag("minecraft:planks"),
        Filters.not(Filters.itemId("minecraft:oak_planks"))
    )
);

Example 5: nested Any(All(...), All(...))

GroupDefinition woodFamilyMixed = new GroupDefinition(
    "mypack:wood_family_mixed",
    "Wood Family Mixed",
    true,
    Filters.any(
        Filters.all(
            Filters.itemTag("minecraft:logs"),
            Filters.itemNamespace("minecraft")
        ),
        Filters.all(
            Filters.itemTag("minecraft:planks"),
            Filters.itemNamespace("create")
        )
    )
);

Example 6: using ExactStack

If you already have an encoded stack string:

String encodedPotionStack = "{\"id\":\"minecraft:potion\",\"count\":1,\"components\":{...}}";

GroupDefinition onePotion = new GroupDefinition(
    "mypack:one_specific_potion",
    "One Specific Potion",
    true,
    Filters.exactStack(encodedPotionStack)
);

If you have an ItemStack instead, use the corresponding overload:

ItemStack stack = ...;
GroupFilter filter = Filters.exactStack(stack);

Both forms resolve to the same ExactStack node. The difference is input type, not meaning.

Notes:

  • ExactStack currently only supports item
  • The JSON equivalent uses the encoded string form
  • fluid and generic types do not have an equivalent exact-stack node

Example 7: using HasComponent for a specific component value

Some mods, such as Apotheosis, use the same item ID with different Data Component values to distinguish variants. ExactStack requires every component to match exactly. If you only want to filter on one component value, use HasComponent.

Single value:

GroupDefinition ballastGems = new GroupDefinition(
    "mypack:apotheosis_ballast_gems",
    "Ballast Gems",
    true,
    Filters.itemComponent("apotheosis:gem", "apotheosis:core/ballast")
);

Multiple values with Any:

GroupDefinition gemsByType = new GroupDefinition(
    "mypack:apotheosis_ballast_or_breaker",
    "Ballast or Breaker Gems",
    true,
    Filters.any(
        Filters.itemComponent("apotheosis:gem", "apotheosis:core/ballast"),
        Filters.itemComponent("apotheosis:gem", "apotheosis:core/breaker")
    )
);

The encodedValue format depends on the component type:

  • ResourceLocation-style components: plain string, e.g. "apotheosis:core/ballast"
  • Numeric components: JSON numeric literal, e.g. "3" or "1.5"
  • Object components: full JSON, e.g. "{\"level\":5}"

Notes:

  • HasComponent currently only supports item
  • If the component ID does not exist or has no codec, the match always returns false
  • Groups that include HasComponent are read-only in the player editor

When the component value is nested: ComponentPath

If the field you want to match is not the whole component value but a specific nested field inside it, use Filters.itemComponentPath().

Iron's Spellbooks stores spell data inside irons_spellbooks:spell_container, with the spell ID at data[0].id. HasComponent compares the whole component value and cannot reach into that structure. ComponentPath can:

GroupDefinition bloodNeedlesScrolls = new GroupDefinition(
    "mypack:blood_needles_scrolls",
    "Blood Needles Scrolls",
    true,
    Filters.all(
        Filters.itemId("irons_spellbooks:scroll"),
        Filters.itemComponentPath(
            "irons_spellbooks:spell_container",
            "data[0].id",
            "irons_spellbooks:blood_needles"
        )
    )
);

The itemId pre-filter is recommended here: it narrows candidates through the item index before the more expensive component-path inspection runs.

DefaultGroupProvider provides a convenience helper that bundles both:

DefaultGroupProvider.itemWithComponentPath(
    "irons_spellbooks:scroll",
    "irons_spellbooks:spell_container",
    "data[0].id",
    "irons_spellbooks:blood_needles"
)

Path grammar:

Pattern Meaning
field top-level key
parent.child nested key
array[n] nth element of an array
array[n].field a field inside an array element

Notes:

  • ComponentPath currently only supports item
  • Groups that use it are read-only in the player editor
  • Use HasComponent when the component value is flat and directly comparable; use ComponentPath when the value you need is nested inside the component's structure

Example 8: generic ingredient type group

Exact ID:

GroupDefinition hydrogen = new GroupDefinition(
    "mypack:hydrogen",
    "Hydrogen",
    true,
    Filters.genericId("mekanism:chemical", "mekanism:hydrogen")
);

Tag and namespace variants:

GroupDefinition mekanismChemicals = new GroupDefinition(
    "mypack:mekanism_chemicals",
    "Mekanism Chemicals",
    true,
    Filters.genericNamespace("mekanism:chemical", "mekanism")
);

Use this when a JEI ingredient type other than item or fluid exists and you want it inside the same group system.


Continue reading:

Home


Players


Modpack Developers


Mod Developers


Localization

Clone this wiki locally