-
Notifications
You must be signed in to change notification settings - Fork 2
Java API
StarskyXIII edited this page Jul 17, 2026
·
3 revisions
Home › Java API
Two things a mod can do with Collapsible Groups: ship built-in default groups, and wire up a custom ingredient type. Both are small.
Be aware of what's stable before depending on anything:
-
Stable:
com.starskyxiii.collapsible_groups.compat.jei.api.CGApi(registerIngredientType,registerIngredientTypeAlias), the KubeJS event surface, and the on-disk formats (Config Reference). -
Everything else — including
GroupDefinition,GroupFilter,Filters— is internal and may move or change without notice.DefaultGroupProviderimplementations compile against these internals, so treat them as "current-version reference", pin loosely, and expect to touch them on mod updates.
Implement DefaultGroupProvider and register it as a Java ServiceLoader service — create META-INF/services/com.starskyxiii.collapsible_groups.defaults.DefaultGroupProvider in your resources containing one line, your implementation's fully qualified class name:
com.example.mymod.MyDefaultGroups
public final class MyDefaultGroups implements DefaultGroupProvider {
@Override
public int priority() {
return 100; // provider load order — lower values load first
}
@Override
public List<GroupDefinition> getGroups() {
return List.of(
// Flat OR groups: the static helpers read nicely
DefaultGroupProvider.group(
"mymod:machines",
"My Machines",
DefaultGroupProvider.item("mymod:crusher"),
DefaultGroupProvider.item("mymod:smelter"),
DefaultGroupProvider.tag("mymod:machine_parts")
),
// Anything fancier: build the filter tree with Filters.*
new GroupDefinition(
"mymod:vanilla_logs_no_oak",
"Vanilla Logs (No Oak)",
true,
Filters.all(
Filters.itemTag("minecraft:logs"),
Filters.itemNamespace("minecraft"),
Filters.not(Filters.itemId("minecraft:oak_log"))
)
)
);
}
}What to know:
-
GroupDefinitionvalidates at construction and throwsIllegalArgumentExceptionon nonsense — fail-fast during dev beats silent breakage for users. - A user/pack file with the same group
idoverrides your built-in version (IDs starting with__default_are reserved and exempt). In-game, your groups are read-only: players can disable them or take a fully editable copy via Copy as Custom. Keepids stable — they're your public interface. - Helpers at a glance:
Filters.any/all/not,itemId/itemTag/itemNamespace,fluidId/fluidTag/fluidNamespace,genericId/genericTag/genericNamespace,blockTag(item-only),itemPathStartsWith/Contains/EndsWith(item-only),exactStack,itemComponent,itemComponentPath.
Here's the part worth reading twice:
- For the in-game editor, you don't need to do anything. Every ingredient type registered with JEI is discovered automatically — it shows up in the editor's Other Types tab, works in rules, icons, and previews. Your mod's JEI plugin is all it takes.
- For KubeJS scripting, registration is still required. KubeJS fixes its event targets before JEI discovery runs, so a script can only target types that were pre-declared:
// During mod init, before KubeJS loads scripts:
CGApi.registerIngredientType("mymod:mytype", MyJeiPlugin.MY_INGREDIENT_TYPE);
CGApi.registerIngredientTypeAlias("mytype", "mymod:mytype");Now pack authors can write:
RecipeViewerEvents.groupEntries('mymod:mytype', event => {
event.group('@mymod', 'mypack:all_my_things', 'All My Things')
})Notes:
-
itemandfluidare reserved. - If you register an explicit ID for a type that auto-discovery also finds, your explicit ID stays canonical and the JEI UID becomes an alias — configs written either way keep working.
- Aliases are pure convenience (
'chemical'vs'mekanism:chemical'); register one if scripts will use your type a lot.
Players
Modpack Developers
Mod Developers
Localization