Skip to content

Java API Providers

StarskyXIII edited this page Mar 25, 2026 · 1 revision

Java API: Providers and Advanced Usage

HomeJava API › Providers and Advanced Usage

This page is for mod developers who want to expose built-in groups from Java and understand how those groups interact with modpacks and the player editor.


When to Read This Page

  • You already know how to build GroupDefinition
  • You want to register default groups through DefaultGroupProvider
  • You need to expose a custom generic ingredient type to KubeJS
  • You want to understand override behavior and editor impact

DefaultGroupProvider: built-in default groups

DefaultGroupProvider is the main entry point for built-in groups. Its goals are:

  • provide a set of default groups at startup
  • keep those groups built into code while still allowing user JSON to override them

Important behavior:

  • priority() defines provider load order
  • getGroups() returns the provider's group list
  • if user JSON uses the same group id, the JSON version overrides the built-in one

Static helpers on DefaultGroupProvider

Besides priority() and getGroups(), the interface provides a set of static helpers:

DefaultGroupProvider.group(String id, String fallbackEnglishName, GroupFilter... filters)
DefaultGroupProvider.item(String itemId)
DefaultGroupProvider.tag(String tagId)
DefaultGroupProvider.tagNs(String tagId, String namespace)
DefaultGroupProvider.tagIntersect(String... tagIds)
DefaultGroupProvider.tagIntersectNs(String namespace, String... tagIds)
DefaultGroupProvider.component(String componentTypeId, String encodedValue)

Where:

  • group(...) returns GroupDefinition
  • the other helpers return GroupFilter

These are convenience helpers. They are not a separate data model, and they are not the only recommended entry point.

Example 9: providing a set of default groups

public final class MyDefaultGroups implements DefaultGroupProvider {
    @Override
    public int priority() {
        return 100;
    }

    @Override
    public List<GroupDefinition> getGroups() {
        return List.of(
            DefaultGroupProvider.group(
                "mypack:utility_blocks",
                "Utility Blocks",
                DefaultGroupProvider.item("minecraft:barrel"),
                DefaultGroupProvider.item("minecraft:crafting_table"),
                DefaultGroupProvider.item("minecraft:chest")
            ),
            new GroupDefinition(
                "mypack:vanilla_logs",
                "Vanilla Logs",
                true,
                Filters.all(
                    Filters.itemTag("minecraft:logs"),
                    Filters.itemNamespace("minecraft")
                )
            )
        );
    }
}

CGApi: exposing a generic JEI ingredient type to KubeJS

If your mod has its own JEI ingredient type and you want KubeJS authors to write:

RecipeViewerEvents.groupEntries('mymod:mytype', event => { ... })

then register that type during initialization.

Example 10: register a generic type for KubeJS

CGApi.registerIngredientType("mymod:mytype", MY_INGREDIENT_TYPE);
CGApi.registerIngredientTypeAlias("mytype", "mymod:mytype");

Notes:

  • item and fluid are reserved types
  • whether an alias exists directly affects what shorthand entry types KubeJS users can write

How the player editor sees Java-defined groups

The player editor tries to decode a GroupFilter into an editable draft. The editable subset is roughly:

  • flat Any(...)
  • item ID / exact stack / item tag
  • fluid ID / fluid tag
  • generic ID / generic tag

If a Java-defined group includes these, the editor usually switches to read-only mode:

  • All
  • Not
  • Namespace
  • HasComponent
  • nested composite structures

That is not a bug. The editor is intentionally limited to flat, low-risk, easy-to-understand editing.

Normalization, validation, and exceptions

GroupDefinition performs normalization and validation at construction time. That means:

  • some structures are reshaped into a more consistent form
  • invalid or incomplete filters throw IllegalArgumentException

That behavior is intentional. Early failure is easier to fix during development than hidden errors that only surface later for users.

Override behavior

The key facts are:

  • built-in default groups are not the absolute final result
  • user JSON can override a built-in group by reusing the same id

So:

  • stable id values matter a lot
  • if you expect pack makers to override your group, make the id, name, and structure easy to understand

When to use Java, and when to hand it off to JSON or KubeJS

Java is a good fit when:

  • the group is part of the mod's feature set
  • you need to tie rules to registration logic, load conditions, or integration flow
  • you need to expose a new generic type to KubeJS

JSON is a good fit when:

  • the rule is static data
  • you want pack makers or users to override it easily
  • you want the rule to be easy to read and review

KubeJS is a good fit when:

  • you want pack authors to take over quickly
  • you want group rules to live with other KubeJS logic
  • the rule belongs to pack script behavior

Recommendations

  • use DefaultGroupProvider helpers for flat OR groups
  • use Filters.* directly for advanced structures
  • use clear localized display names for formal built-in groups
  • treat read-only editor behavior as a design decision when it is intentional
  • keep stable id values for groups that packs may override
  • avoid documenting imaginary builder-chain APIs; the public model uses a helper-and-constructor pattern