Pixel Dream StudiosWiki
Mods

Unbound World Wiki

A difficulty and world progression mod inspired by games like Terraria.

Unbound World

Terraria-style world progression - bosses gate items, blocks, ores, dimensions, and mob difficulty as the world advances through stages.

Overview

Unbound World locks the world into a starting state called Sealed World. Defeating a stage's designated boss advances the world's stage order by one, which can unlock:

  • Items and tools/armor sets
  • Blocks (functional blocks like Enchanting Tables, or ore blocks)
  • Dimensions
  • Additional optional ("preparation") bosses
  • Increased mob health, damage, knockback resistance, and armor
  • Custom equipment on humanoid mobs

Progression is world-wide, not per player. Every player on the server shares the same unlocked stage.

Unbound World does not generate its own bosses or dimensions. It reads stage definitions from data-driven JSON files and reacts to vanilla (or modded) entity kills, block breaks, and dimension travel.

Supported environment

  • Minecraft 1.21.1, 26.1.2
  • NeoForge
  • Optional soft dependencies: Jade (tooltip integration)
  • Mod ID: unbound_world

Core concept: World Stage

The world's progress is tracked as a single integer, the unlocked order, stored persistently per-world.

ValueMeaning
-1Sealed World - nothing unlocked yet
0First stage cleared
1, 2, 3...Subsequent stages cleared, in order

An item, block, ore, dimension, or boss is locked if the stage that owns it has an order greater than the current unlocked order. Defeating that stage's main boss advances the world to that stage's order, unlocking everything registered to it at once.

Stage data files

Stages are defined as JSON files at:

data/<namespace>/stages/<stage_name>.json

The reload listener scans every namespace for a stages folder - the file's own namespace does not need to match the mod ID, and the filename itself has no meaning to the game (it is not read as part of the stage's identity).

Complete field reference

{
  "order": 2,
  "stage_translation_key": "stage.unbound_world.hellfire",

  "mob_attribute_scaling": {
    "health_multiplier": 1.5,
    "damage_multiplier": 1.35,
    "knockback_resistance_multiplier": 1.05,
    "armor_multiplier": 1.15
  },

  "mob_equipment": [
    {
      "entity_ids": ["minecraft:piglin", "minecraft:piglin_brute"],
      "equipment": [
        {
          "slot": "mainhand",
          "item": "minecraft:golden_sword",
          "enchantments": [
            { "id": "minecraft:sharpness", "level": 1 }
          ],
          "drop_chance": 0.02
        }
      ]
    }
  ],

  "locked_ores": [
    { "ore_block": "minecraft:ancient_debris", "disguise_block": "minecraft:netherrack" }
  ],

  "main_boss": {
    "entity_id": "minecraft:wither",
    "display_item": "minecraft:nether_star",
    "location_translation_key": "boss.unbound_world.wither.location",
    "guaranteed_drops": ["minecraft:nether_star"],
    "player_scaling": {
      "radius": 48.0,
      "health_per_extra_player": 0.5,
      "damage_per_extra_player": 0.2,
      "knockback_resistance_per_extra_player": 0.0,
      "armor_per_extra_player": 0.0
    },
    "drops": {
      "mode": "additional",
      "drops": [
        { "item": "minecraft:netherite_scrap", "count_min": 2, "count_max": 4, "chance": 1.0 }
      ]
    }
  },

  "optional_bosses": [
    {
      "entity_id": "minecraft:blaze",
      "display_item": "minecraft:blaze_rod",
      "location_translation_key": "boss.unbound_world.blaze.location",
      "guaranteed_drops": [],
      "player_scaling": { "radius": 32.0, "health_per_extra_player": 0.0, "damage_per_extra_player": 0.0, "knockback_resistance_per_extra_player": 0.0, "armor_per_extra_player": 0.0 },
      "drops": { "mode": "additional", "drops": [] }
    }
  ],

  "locked_items": ["minecraft:netherite_sword"],
  "locked_blocks_to_mine": ["minecraft:brewing_stand"],
  "locked_dimensions": ["minecraft:the_end"]
}

order

Type: integer, required

The stage's position in progression. Determines when its unlocks become available and what a boss defeat advances the world to.

stage_translation_key

Type: string, required

The translation key for the stage's display name in the Guide UI. A matching <key>.summary key is also expected for the short description shown at the top of the stage's detail view.

mob_attribute_scaling

Type: object, optional. Default: all multipliers 1.0 (no change).

Applies to every hostile mob (anything extending Monster - Zombie, Skeleton, Spider, etc.) while this stage is the currently active one. Passive and neutral mobs (cows, villagers, etc.) are never affected.

FieldDefaultEffect
health_multiplier1.0Extra max health, e.g. 1.5 = +50%
damage_multiplier1.0Extra attack damage
knockback_resistance_multiplier1.0Extra knockback resistance
armor_multiplier1.0Extra armor value

Only applies to newly spawned mobs - a mob already in the world does not retroactively gain the bonus when the stage changes.

Values of 1.0 or less have no effect. This field cannot currently reduce a mob below its vanilla baseline.

mob_equipment

Type: list, optional.

Equips specific weapons/armor onto matching mob types while this stage (or any earlier one, see below) is active. Grouped by entity_ids so many mobs can share one loadout.

{
  "entity_ids": ["minecraft:zombie", "minecraft:husk", "minecraft:drowned"],
  "equipment": [
    {
      "slot": "mainhand",
      "item": "minecraft:iron_sword",
      "enchantments": [{ "id": "minecraft:sharpness", "level": 1 }],
      "drop_chance": 0.02
    }
  ]
}

slot accepts mainhand, offhand, head, chest, legs, feet. drop_chance defaults to 0.0 (the item never drops on death) unless set otherwise.

Inheritance: if a later stage does not redefine equipment for a given entity, the highest earlier stage that does define it is used automatically. To explicitly stop a mob's equipment at some stage, give that entity an empty "equipment": [] in that stage.

Works with any registered item or enchantment, vanilla or modded - resolution is purely by ID, not by hardcoded type.

locked_ores

Type: list, optional.

Ore blocks that remain fully minable while locked, but are visually disguised as another block and yield that block's item instead of the real ore.

{ "ore_block": "minecraft:diamond_ore", "disguise_block": "minecraft:stone" }

This is distinct from locked_blocks_to_mine: an ore in this list can always be broken (it is never fully inaccessible), only its appearance and drop change while sealed.

main_boss / optional_bosses

main_boss is the boss whose death advances the world to this stage's order. optional_bosses are additional bosses tied to the stage for guide/flavor purposes and drop configuration, but killing one does not advance progression.

Both use the same structure:

FieldDefaultPurpose
entity_idrequiredThe boss's entity type
display_itemminecraft:barrierIcon shown in the Guide UI
location_translation_key""Optional spawn/location hint text, shown in the Guide UI. Leave empty to hide the section entirely
guaranteed_drops[]Items always included in the drop preview and (for the actual drop logic, see below) - needed for bosses whose real drop is hardcoded in Java rather than their loot table (e.g. the Wither's Nether Star)
player_scalingno-opPer-boss attribute scaling based on how many players are near the boss when it spawns (see below)
drops{ "mode": "none", "drops": [] }Custom drop table, see below
player_scaling
{
  "radius": 48.0,
  "health_per_extra_player": 0.5,
  "damage_per_extra_player": 0.2,
  "knockback_resistance_per_extra_player": 0.0,
  "armor_per_extra_player": 0.0
}

At spawn, the boss counts alive players within radius blocks. For every player beyond the first, the listed fractions are added (e.g. health_per_extra_player: 0.5 with 3 nearby players adds +100% health). A solo player triggers no bonus. This does not update dynamically if players join or leave mid-fight - it is evaluated once, at spawn.

drops
{
  "mode": "additional",
  "drops": [
    { "item": "minecraft:netherite_scrap", "count_min": 2, "count_max": 4, "chance": 1.0 }
  ]
}
ModeEffect
noneVanilla drops only, unmodified. Custom drops list is ignored
additionalVanilla drops plus the custom drops list
replaceOnly the custom drops list - vanilla loot table is skipped entirely

guaranteed_drops is separate from this table: it exists because some vanilla bosses spawn their signature item directly in Java code rather than through their loot table (the Wither's Nether Star is the primary example). Without listing it here, the Guide UI's drop preview and any future guaranteed-drop logic would not know about it - the loot table itself genuinely does not contain it.

locked_items

Type: list of item IDs, optional.

Fully inaccessible while locked - cannot be picked up meaningfully, equipped, used, or crafted with while the owning stage is not yet reached. Shown with a "Sealed" tooltip everywhere the item appears.

locked_blocks_to_mine

Type: list of block IDs, optional.

Fully inaccessible while locked - cannot be broken or placed at all. Intended for functional blocks (Enchanting Table, Anvil, Beacon, redstone components) rather than naturally-generated ore, which should use locked_ores instead.

locked_dimensions

Type: list of dimension IDs, optional.

Blocks travel into the listed dimension via any portal while the owning stage has not been reached. The player is stopped before the actual dimension change happens; nothing else about the portal is altered.

How locking actually works

Items and blocks

Every relevant interaction is intercepted: right-click use, left-click attack, block breaking/placing, shift-click auto-equip, drag-and-drop into armor slots, crafting result pickup, and attribute modifiers (a locked weapon's damage bonus is stripped while sealed). Creative-mode players bypass all of this.

Ores

Unlike a fully locked block, a locked ore can always be mined. Breaking it yields the configured disguise_block's item instead of the real ore, and - while the world is rendered - the block visually appears as the disguise block (mesh, breaking particles, and block-break sound all use the disguise), not the true block. The true block state is never altered; only the client's rendering and the resulting drop are affected. When the owning stage is reached, all loaded chunks are refreshed immediately so previously-disguised ore reveals its true appearance without needing to reload the world.

Bosses

A boss (main or optional) cannot be damaged at all until the stage before its own has been cleared. Attacking one that is still locked is silently canceled and the attacker sees a message naming the stage that must be cleared first. Creative-mode players bypass this.

Dimensions

Attempting to travel into a locked dimension through a portal is canceled before the actual dimension change occurs. This only intercepts genuine portal travel - a command-based teleport (/execute in ...) or a different mod's custom teleport mechanism is not affected.

Commands

All commands require operator permission level 2 and live under /unbound stage.

CommandEffect
/unbound stage getShows the current stage's name, or "Sealed World"
/unbound stage set <order>Manually sets the world's unlocked order and re-evaluates locked equipment/attributes
/unbound stage resetResets the world back to Sealed World (-1)

The Guide

Players can open an in-game progression guide (default keybind: K) showing:

  • Every known stage, with a checkmark if it has been cleared
  • A stage's main boss, optional bosses, and every sealed item/block/ore tied to it
  • A boss's location hint (if configured) and its full drop preview, including vanilla drops resolved via loot table simulation

Examples

A stage with no restrictions beyond its boss

{
  "order": 0,
  "stage_translation_key": "stage.unbound_world.raiders_dawn",
  "main_boss": {
    "entity_id": "minecraft:evoker",
    "display_item": "minecraft:totem_of_undying",
    "drops": { "mode": "additional", "drops": [
      { "item": "minecraft:totem_of_undying", "count_min": 1, "count_max": 1, "chance": 1.0 }
    ] }
  },
  "locked_items": ["minecraft:totem_of_undying"]
}

Locking an entire ore tier plus its tools and armor

{
  "order": 1,
  "stage_translation_key": "stage.unbound_world.echoes",
  "locked_ores": [
    { "ore_block": "minecraft:diamond_ore", "disguise_block": "minecraft:stone" },
    { "ore_block": "minecraft:deepslate_diamond_ore", "disguise_block": "minecraft:deepslate" }
  ],
  "locked_items": [
    "minecraft:diamond",
    "minecraft:diamond_sword", "minecraft:diamond_pickaxe", "minecraft:diamond_axe",
    "minecraft:diamond_shovel", "minecraft:diamond_hoe",
    "minecraft:diamond_helmet", "minecraft:diamond_chestplate",
    "minecraft:diamond_leggings", "minecraft:diamond_boots"
  ]
}

A boss whose signature drop is hardcoded (not in its loot table)

{
  "entity_id": "minecraft:wither",
  "display_item": "minecraft:nether_star",
  "guaranteed_drops": ["minecraft:nether_star"],
  "drops": { "mode": "additional", "drops": [] }
}

Gating the Nether behind a stage

{
  "order": 2,
  "stage_translation_key": "stage.unbound_world.sculk_dread",
  "locked_dimensions": ["minecraft:the_nether"],
  "main_boss": { "entity_id": "minecraft:warden", "display_item": "minecraft:echo_shard" }
}

Troubleshooting

A stage doesn't load / doesn't appear in the Guide

Check that order and stage_translation_key are both present - they are the only two required fields. Check the server log for a JSON parsing error; a required field with no default (only order and stage_translation_key) will fail the whole file silently otherwise.

Two stages have the same order

Both will be treated as unlocked/locked together, and the Guide will list both. This is usually a mistake - give each stage a unique order.

An item/block still works after being listed in locked_items / locked_blocks_to_mine

Confirm the player is not in Creative mode (Creative always bypasses locks by design). Confirm the ID is spelled correctly and namespaced (minecraft: prefix for vanilla items).

A boss can be damaged before its "unlock stage" is reached

The lock only applies to the stage immediately before the boss's own stage. A boss at order: 2 is only locked while the world is below order: 1 - it becomes damageable the moment order: 1 is cleared, even before order: 2 itself is reached. This is intentional (you must be able to fight the boss to reach its stage).

A player can still enter a locked dimension

Only genuine portal travel is intercepted. Command-based teleports and third-party mod teleport mechanisms are not covered.

An ore's optical disguise doesn't update immediately after unlocking

Confirm the client actually received the updated stage order - a fresh chunk render is triggered automatically on stage change, but a very laggy connection could delay this by a moment.

Frequently asked questions

Is progression per-player or world-wide?

World-wide. Every player shares the same unlocked stage.

Can a locked ore never be mined at all?

No - locked ores are always minable. Only their appearance and drop are affected while sealed. Use locked_blocks_to_mine instead if a block should be completely inaccessible.

Do Creative players bypass locks?

Yes, on every lock type (items, blocks, bosses, dimensions).

What happens to a stage's optional bosses if their stage is never reached?

They remain locked the same way the main boss does - damage is canceled until the previous stage is cleared.

Can I use modded items, blocks, entities, or enchantments anywhere in a stage file?

Yes. Every reference is resolved purely by registry ID (namespace:path) - there is no hardcoded vanilla-only list anywhere in the lock, drop, equipment, or ore-disguise systems.

For developers: building an addon

Unbound World exposes a small, stable API surface intended for addon mods (a future Bosses module, a Looting Bags module, or third-party content packs). Depend on unbound_world as a normal mod dependency, but only reference the classes below - internal classes such as StageManager may change between versions without notice.

Reading progression state

import net.veroxuniverse.unbound_world.api.UnboundWorldApi;

int order = UnboundWorldApi.getUnlockedOrder();
boolean locked = UnboundWorldApi.isItemLocked(ResourceLocation.parse("minecraft:diamond_sword"));
Optional<StageDefinition> current = UnboundWorldApi.getCurrentStage();

Available methods: getUnlockedOrder(), getAllStages(), getStageByOrder(int), getCurrentStage(), isItemLocked(ResourceLocation), isBlockLocked(ResourceLocation), isOreLocked(ResourceLocation), isDimensionLocked(ResourceLocation), isBossLocked(ResourceLocation), getOwningStageForBoss(ResourceLocation), getBossInfo(ResourceLocation), isRegisteredBoss(ResourceLocation).

Reacting to progression events

Two events are posted on NeoForge.EVENT_BUS:

StageUnlockedEvent - fired whenever the world's stage order changes, including manual changes via /unbound stage set or reset. Not cancellable; the change has already happened.

@SubscribeEvent
public static void onStageUnlocked(StageUnlockedEvent event) {
    event.getNewStage().ifPresent(stage -> {
        // e.g. spawn addon-specific content for this stage
    });
}

BossDefeatedEvent - fired after a registered boss (main or optional, from any loaded stage) is killed by a player, once Unbound World's own drop and progression handling has already run. Intended for addons that want to react to a boss kill independently - for example, a Looting Bags addon granting a bag in addition to (or instead of) the normal drop through its own separate handler.

@SubscribeEvent
public static void onBossDefeated(BossDefeatedEvent event) {
    if (event.wasMainBoss()) {
        // give the killer a loot bag matching event.getOwningStage()
    }
}

What addons should not do

  • Do not write to StageManager's internal maps directly, even though the class is technically public - always go through the events above to react, and never assume its internal structure will stay the same between versions.
  • Do not assume a stage's order values are contiguous or start at 0 - always compare relatively (>=, >), never hardcode an expected sequence.
  • Do not rely on player_scaling or mob_attribute_scaling updating dynamically after a mob has already spawned - both are spawn-time only.

On this page