🔒 Looking for Beta Testers! Found a bug? Report it on our Discord or GitHub — every report helps shape the stable release.
ProgressiveStages 2.0 is the most complete progression-control framework available for NeoForge 1.21.1. Built for modpack developers who want players to actually earn their way through content — not skip straight to endgame on day one.
Lock items, blocks, fluids, recipes, crops, enchantments, dimensions, mobs, interactions, loot rolls, GUIs, pet interactions, structures, and 3D regions behind meaningful progression milestones. Players unlock stages through exploration, quests, advancements, boss kills, item pickups, or any combination of those events. No more sequence breaking. No more bypassing your carefully crafted progression curve.
If you've ever wanted Gamestages — but on modern NeoForge, with depth, with team support, with EMI/JEI integration, and with the kind of safety nets that survive real modpacks — this is it.
2.0 is a ground-up rewrite of the locking model. Every category now uses the same unified prefix system, the same [unlocks] carve-out grammar, and the same per-stage [enforcement] exemptions. New surfaces, new triggers, and a completely rewritten config schema:
id: / mod: / tag: / name: / # all work in every locked list, across every category.[[multi]] trigger requirements — gate a stage behind a set of conditions ("own a stone sword AND a stone pickaxe AND a stone axe"). Mix item:, advancement:, dimension:, and boss: sub-triggers freely, with all_of or any_of semantics.[crops] — full crop-progression gating: planting, growth, bonemeal, harvest.[enchants] — gate enchantments at the table, the anvil, villager trades, AND strip them from existing gear on inventory scan.[mobs] — gate spawning of specific mobs (or whole mod namespaces, or tags). Includes dynamic replacement — swap an unwanted spawn for a friendlier mob automatically.[pets] — separately gate taming, breeding, commanding, and riding for animals.[screens] — one list gates every GUI surface, including held-item GUIs (backpacks, portable workstations, held shulker boxes).[structures] — gate entry to vanilla and modded structures, lock chests inside them, prevent block break/place/explosions/spawns inside the bounding box.[[regions]] — define hand-authored 3D boxes per dimension with their own flags and debuffs.[loot] — a single list filters chest, fishing, archeology, mob-drop, and block-drop rolls through a Global Loot Modifier. Lootr is supported out of the box.[curios] — per-slot gating when Curios is installed.[[interactions]] — fine-grained "item-on-block" / "item-on-entity" / "right-click-this-block" rules for Create-style and modded interactions./stage progress command — next shows what you can unlock right now (with per-trigger ✓/✗), all shows the full roadmap, <stage> shows the breakdown for one specific stage.&-color codes and placeholders.[unlocks] carve-outs — broad locks (mod:ae2, name:diamond) can carve out specific exceptions on a per-stage basis.[enforcement] per-stage exemptions — let players stockpile raw materials before unlocking the use of them.Every category below uses the same unified prefix system. You can mix and match id: / mod: / tag: / name: entries in any list:
| Prefix | Meaning | Example |
|---|---|---|
id:<namespace:path> |
Exact registry ID | id:minecraft:diamond |
| (no prefix) | Implicit id: |
minecraft:diamond |
mod:<namespace> |
Entire mod namespace | mod:ae2 |
tag:<namespace:path> |
A registry tag | tag:minecraft:logs |
name:<substring> |
Case-insensitive substring of the full ID | name:netherite |
#<namespace:path> |
Legacy tag shorthand | #minecraft:crops |
locked_ids) OR by output item (locked_items). Hide locked recipes from EMI/JEI entirely or show them with overlays.[entities] blocks attacking specific entity types.[[interactions]] lets you gate block_right_click, item_on_block, and item_on_entity events in fine detail.[loot] list.locked_spawns cancels finalizeSpawn-based spawns. Dynamic replacement ([[mobs.replacements]]) lets you swap one mob for another at spawn time.prevent_block_break, prevent_block_place, prevent_explosions, disable_mob_spawning.Every category supports always_unlocked = [...] for exact-ID exceptions. Lock all of Mekanism but keep the Configurator usable:
[items]
locked = ["mod:mekanism"]
always_unlocked = ["mekanism:configurator"]
And per-stage [unlocks] carves out exceptions in even broader scopes — see the docs for the full grammar.
Triggers live in one file (config/ProgressiveStages/triggers.toml). Stages grant themselves when players:
[advancements][items] (also scans inventory at login to catch players who already have it)[dimensions] (one-time, persisted per-world)[bosses] (one-time, persisted per-world)[[multi]] — compound trigger requirementsThe headline 2.0 trigger feature. Require MULTIPLE conditions before a stage is granted:
[[multi]]
stage = "stone_tools_master"
description = "Own a full set of stone tools"
all_of = [
"item:minecraft:stone_sword",
"item:minecraft:stone_pickaxe",
"item:minecraft:stone_axe",
]
Mix surfaces freely — items, advancements, dimensions, bosses:
[[multi]]
stage = "endgame"
description = "Beat the major bosses + reach the End + survive once"
all_of = [
"boss:minecraft:ender_dragon",
"boss:minecraft:wither",
"dimension:minecraft:the_end",
"advancement:minecraft:adventure/totem_of_undying",
]
Use any_of instead of all_of for "satisfy any one route" gating. Per-player progress is persisted across restarts; retroactive credit on login is given for item / advancement / dimension surfaces (boss kills must be re-earned).
Stages declare other stages as prerequisites — single string or list. The dependency graph is an arbitrary DAG, validated at load time:
Linear progression — the classic tier chain:
🪨 stone_age
└── ⚙️ iron_age
└── 💎 diamond_age
└── 🔮 netherite_age
Branching paths — tech and magic unlock separately:
🪨 stone_age
├── ⚙️ iron_age
│ ├── 💎 diamond_age
│ └── 🏭 tech_age
│ └── ☢️ nuclear_age
└── 📚 magic_age
├── 🔮 arcane_age
└── 🌿 nature_age
Multi-dependency gates — require multiple paths before unlocking endgame:
🪨 stone_age
├── ⚙️ iron_age ──────────────────┐
│ └── 💎 diamond_age ───────┤
│ ▼
└── 📚 magic_age ─────────► 🌌 endgame_age
└── 🔮 arcane_age ────────┘
(requires BOTH diamond_age AND arcane_age)
Parallel independent trees — some stages have no dependencies at all:
🪨 stone_age 🌿 nature_age 🗺️ exploration_age
└── ⚙️ iron_age └── 🔮 druid_age └── 🌋 nether_age
└── 💎 diamond_age └── 🐉 end_age
With linear_progression = true, granting a stage auto-grants every missing dependency up the chain. With it false, /stage grant warns about missing dependencies and requires a second confirmation to bypass.
The best visual lock experience available for 1.21.1:
reveal_stage_names_only_to_operators)persist_stages_on_leave — keep a player's stages when they leave the teamNative, deep integration:
stone_age, iron_age, diamond_age, plus triggers.toml on first launch. The diamond_age.toml template is the canonical 2.0 reference, with every category and field documented inline./progressivestages reload re-parses all stage TOMLs and re-syncs every online player, no restart required/progressivestages validate parses every stage file with detailed error reporting and warns about dependency issues before your players find them/stage progress — show players exactly what they can unlock next, the full roadmap, or the per-trigger breakdown for one specific stageToggle any enforcement type independently — items, recipes, blocks, entities, dimensions, interactions, mobs, crops, pets, screens, loot, enchants, regions, structures.
[enforcement] exemptions — let players stockpile raw diamonds before unlocking the use of diamonds: [items]
locked = ["name:diamond"]
[enforcement]
allowed_pickup = ["minecraft:diamond"]
allowed_inventory = ["minecraft:diamond"]
reveal_stage_names_only_to_operators hides stage IDs from non-op players for spoiler-free progressionPlayer-facing
/stage list [player] — list a player's stages/stage check <player> <stage> — boolean check/stage info <stage> — stage metadata: id, dependencies, description, lock count/stage tree — ASCII dependency tree of every loaded stage/stage progress — what the caller can unlock right now/stage progress next [player] — every reachable stage + per-trigger ✓/✗ breakdown/stage progress all [player] — full roadmap, including unreachable stages/stage progress <stage> [player] — per-trigger breakdown for one specific stageAdmin
/stage grant <player> <stage> — grant a stage (prompts for confirmation if dependencies are missing)/stage revoke <player> <stage> — revoke a stage/progressivestages reload — reload every stage file + triggers.toml, re-sync online players/progressivestages validate — detailed parse + dependency check across every stage file/progressivestages ftb status [player] — diagnostics for the FTB Quests integration/progressivestages trigger reset <player> <type> <key> — clear a persisted trigger (dimension, boss, multi)/progressivestages multi list [player] — every [[multi]] requirement and (with a player) their per-requirement progress/progressivestages no-creative-popup — per-player toggle for the creative-bypass popupILootrFilterProvider ServiceLoaderThe mod ships with an exhaustive DOCUMENTATION.md covering every TOML field, every config key, every command, every integration, and every troubleshooting tip. Read it on GitHub, or grab the file out of the jar.
Open an issue on GitHub or drop it in our Discord. ProgressiveStages 2.0 is actively developed and every report gets looked at. We're building toward a stable 1.0 release and your feedback directly shapes what comes next.