Register Advancements
Simple Advancement (Root + Child)
REGISTRYLIB.addDataGenerator(
ProviderType.ADVANCEMENT,
adv -> {
String cat = MOD_ID;
AdvancementHolder root = Advancement.Builder.advancement()
.display(
Items.CRAFTING_TABLE,
adv.title(cat, "simple/root", "Getting Started"),
adv.desc(cat, "simple/root", "Obtain a crafting table"),
Identifier.withDefaultNamespace(
"textures/gui/advancements/backgrounds/stone.png"),
AdvancementType.TASK,
false, false, false)
.addCriterion(
"has_crafting_table",
InventoryChangeTrigger.TriggerInstance.hasItems(Items.CRAFTING_TABLE))
.save(adv, Identifier.fromNamespaceAndPath(cat, "simple/root"));
Advancement.Builder.advancement()
.parent(root)
.display(
COPPER_COIN.get(),
adv.title(cat, "simple/get_coin", "First Coin"),
adv.desc(cat, "simple/get_coin", "Pick up a Copper Coin"),
null,
AdvancementType.TASK,
true, true, false)
.addCriterion(
"has_coin",
InventoryChangeTrigger.TriggerInstance.hasItems(COPPER_COIN.get()))
.save(adv, Identifier.fromNamespaceAndPath(cat, "simple/get_coin"));
});
Full Multi-Tab Example
REGISTRYLIB.addDataGenerator(
ProviderType.ADVANCEMENT,
adv -> {
String cat = MOD_ID;
// --- Tab 1: Basics ---
AdvancementHolder root = Advancement.Builder.advancement()
.display(
COPPER_COIN.get(),
adv.title(cat, "basics/root", "RegistryCore Basics"),
adv.desc(cat, "basics/root", "Getting started with RegistryCore"),
Identifier.withDefaultNamespace(
"textures/gui/advancements/backgrounds/stone.png"),
AdvancementType.TASK,
false, false, false)
.addCriterion(
"has_crafting_table",
InventoryChangeTrigger.TriggerInstance.hasItems(Items.CRAFTING_TABLE))
.save(adv, Identifier.fromNamespaceAndPath(cat, "basics/root"));
AdvancementHolder getCoin = Advancement.Builder.advancement()
.parent(root)
.display(
COPPER_COIN.get(),
adv.title(cat, "basics/get_coin", "First Coin"),
adv.desc(cat, "basics/get_coin", "Obtain a Copper Coin"),
null,
AdvancementType.TASK,
true, true, false)
.addCriterion(
"has_coin",
InventoryChangeTrigger.TriggerInstance.hasItems(COPPER_COIN.get()))
.save(adv, Identifier.fromNamespaceAndPath(cat, "basics/get_coin"));
Advancement.Builder.advancement()
.parent(getCoin)
.display(
MAGIC_WAND.get(),
adv.title(cat, "basics/get_magic_wand", "Arcane Discovery"),
adv.desc(cat, "basics/get_magic_wand", "Craft a Magic Wand"),
null,
AdvancementType.GOAL,
true, true, false)
.addCriterion(
"has_magic_wand",
InventoryChangeTrigger.TriggerInstance.hasItems(MAGIC_WAND.get()))
.save(adv, Identifier.fromNamespaceAndPath(cat, "basics/get_magic_wand"));
// --- Tab 2: Advanced ---
AdvancementHolder advRoot = Advancement.Builder.advancement()
.display(
MAGIC_ORE.get().asItem(),
adv.title(cat, "advanced/root", "Advanced Crafting"),
adv.desc(cat, "advanced/root", "Explore advanced features"),
Identifier.withDefaultNamespace(
"textures/gui/advancements/backgrounds/nether.png"),
AdvancementType.TASK,
false, false, false)
.addCriterion(
"has_iron",
InventoryChangeTrigger.TriggerInstance.hasItems(Items.IRON_INGOT))
.save(adv, Identifier.fromNamespaceAndPath(cat, "advanced/root"));
Advancement.Builder.advancement()
.parent(advRoot)
.display(
TIMER_TIER_3.get().asItem(),
adv.title(cat, "advanced/build_timer", "Time Lord"),
adv.desc(cat, "advanced/build_timer", "Craft a Tier 3 Timer"),
null,
AdvancementType.CHALLENGE,
true, true, true)
.addCriterion(
"has_timer_3",
InventoryChangeTrigger.TriggerInstance.hasItems(TIMER_TIER_3.get().asItem()))
.save(adv, Identifier.fromNamespaceAndPath(cat, "advanced/build_timer"));
});
Core API
Entry Point
REGISTRYLIB.addDataGenerator(ProviderType.ADVANCEMENT, adv -> { ... });
Hooks your advancement tree into RegistryLib's datagen pipeline.
Localization Helpers
| Method | Generated Key Format |
|---|---|
adv.title(cat, name, text) | advancements.<cat>.<name>.title |
adv.desc(cat, name, text) | advancements.<cat>.<name>.description |
Display Parameters
.display(icon, title, description, background, type, showToast, announceToChat, hidden)
background—only relevant for root advancements (passnullfor children)hidden—keeps the advancement invisible until unlocked
Tree Structure
.parent(holder)—set the parent advancement.save(adv, id)—write the JSON and return anAdvancementHolderfor children to reference
AdvancementType
| Type | Use Case |
|---|---|
TASK | Standard progression step |
GOAL | Significant milestone |
CHALLENGE | Difficult or hidden achievement |
Common Patterns
One root + children: Every tab needs exactly one root advancement (the one with a background texture). All others chain via .parent(...).
Multiple tabs: Each root with a distinct background texture creates a separate tab in the advancement screen. Use consistent path prefixes (basics/..., advanced/...) for organization.
Hidden challenges: Set the last three .display(...) booleans to true, true, true to create a hidden challenge that shows a toast and chat announcement on unlock.
important
The root advancement in each tab should provide the background texture. Child advancements pass null for the background parameter.