The mod is the engine: worldgen, instanced dimensions, portals, keys, waves, bosses, rules, and rewards. You add your own dungeons as JSON (and optional SNBT rooms) without writing Java.
The jar ships three example dungeons so you can test the engine and copy the format. They are optional. Delete or disable them and ship only your content.
customdungeondata/<namespace>/dungeons/<name>/- and |; stack floors for 3D mapsconfig/customdungeon/dungeons/ without repackingThree examples are included so you can play, copy, or delete them. The mod works with zero of them. Put your own folders under data/<namespace>/dungeons/ (or disable the examples below).
| Dungeon | Where | How you enter |
|---|---|---|
Ancient Crypt (example_crypt) |
Overworld forests, plains, taiga, hills | Surface shrine. Hold stone and a bound dungeon key, then use the portal. |
Ashen Bastion (example_nether) |
The Nether | Full fortress generated in the world. Walk in (protected rooms, mobs, entrance). Also /cd start. |
End Citadel (example_end) |
End highlands / midlands | Embedded SNBT citadel. Walk in, or /cd start. |
To remove the examples from a pack:
config/customdungeon/dungeons/<name>/dungeon.json, set "enabled": false for example_crypt, example_nether, and example_end.Already-generated chunks will not grow new shrines or embeds. Explore new terrain, start a new world, or use /cd place <id>.
/cd locate example_crypt if you are op) or /cd place example_crypt.Walk into the structure. Rooms are protected, encounters spawn, and leaving unbinds you in place (you stay in that dimension).
| Item | Recipe / use |
|---|---|
| Dungeon Key | Gold ingots around an ender pearl. Bind on a shrine, or NBT Dungeon:"namespace:id". |
| Dungeon Sigil | Stone + ender pearls + a key. Right-click to teleport to the bound shrine / world dungeon. |
| Dungeon Exit Token | Creative tab / loot. Leaves the current instance run. |
/give @p customdungeon:dungeon_key{Dungeon:"customdungeon:example_crypt"} 1
Alias: /cd. Ids can be example_crypt or customdungeon:example_crypt.
/customdungeon list
/customdungeon info <id>
/customdungeon start <id>
/customdungeon leave
/customdungeon locate [id] # op — clickable coords in front of the shrine
/customdungeon place <id> # op — shrine or embed at your feet
/customdungeon reload # op — config overlay only (use /reload for datapacks)
/customdungeon complete # op — force-clear the current run
Vanilla:
/locate customdungeon:dungeon_shrine
Each dungeon is one folder:
data/<namespace>/dungeons/<name>/
dungeon.json required
portal.json optional — merged into dungeon.portal
rooms/<room>.json procedural (or SNBT) room templates
rooms/<room>.snbt structure-block export as a room
encounters/<id>.json waves / boss
Dungeon id is <namespace>:<name> unless dungeon.json sets "id".
Relative refs ("encounters": ["skeletons"]) resolve to <namespace>:<name>/skeletons.
Omitted keys use defaults. Only write what you change.
Vanilla /reload reloads datapacks. /cd reload reloads config/customdungeon/dungeons/ only.
The mod provides empty dimension customdungeon:dungeon for instanced runs. Point portal.dimension at it, or at your own datapack dimension.
{
"display": { "name": "My Crypt" },
"natural_spawn": {
"enabled": true,
"dimensions": ["minecraft:overworld"],
"biomes": ["#is_forest"],
"rarity": 48
},
"layout": {
"shape": ["E-H-B"],
"rooms": [
{ "id": "entrance", "encounters": ["skels"] },
{ "id": "hall", "encounters": ["skels"] },
{ "id": "boss", "encounters": ["boss"] }
]
}
}
{
"activation": "both",
"frame": "minecraft:stone_bricks",
"catalyst": "minecraft:stone"
}
Put the portal object in portal.json or under "portal" in dungeon.json.
"natural_spawn": {
"enabled": true,
"embed": true,
"dimensions": ["minecraft:the_nether"],
"layer": "nether",
"min_y": 40,
"max_y": 90,
"rarity": 24
}
shapeLetters are rooms. - | + link them. A 2D list is one floor; a list of lists stacks floors on Y.
"shape": [
[" G ", " | ", "E-H-B"],
[" A ", " | ", " T "]
],
"cells": { "E": "entrance", "H": "hall", "B": "boss", "G": "graves", "A": "chapel", "T": "treasury" }
If cells is omitted, the letter matches the room id prefix. start_room defaults to the first room.
Procedural rooms get a corridor of gap blocks. SNBT rooms sit wall-to-wall (doors punched).
Other layouts: omit shape for a linear row; "type": "grid" with grid_x / grid_z; or set x / z / next for exact offsets.
Defaults apply when a key is missing.
dungeon.json| Field | Default | Notes |
|---|---|---|
id |
folder id | Override registry name. |
enabled |
true |
false = loaded but never starts / generates. |
display.name |
path | Chat title on enter. |
display.description |
"" |
Sent after enter. |
natural_spawn |
off | Alias: placement (overlay, natural_spawn wins). |
portal |
off unless catalyst / frame / activation | Can live in portal.json. |
entry |
command + key + portal | Who can enter. |
instance |
customdungeon:dungeon |
Instance world + reset. |
layout |
one empty room | Room graph. |
rules |
see below | Combat / grief / death. |
rewards |
none | on_complete / on_fail / on_room_clear. |
natural_spawn| Field | Default | Notes |
|---|---|---|
enabled |
false |
true = generate in the world. |
embed |
false |
true = place rooms in the world. false = shrine portal only. |
dimensions |
overworld | Dimension ids. |
biomes |
all | Exact id, category:jungle, or tags (#is_forest, #nether, #end, …). |
biome_blacklist |
[] |
Same syntax. Blacklist wins. |
layer |
surface |
surface (heightmap), nether (air above solid), sky (max_y). |
min_y / max_y |
5 / 80 |
Used for nether / sky embeds. Shrines sit on the surface. |
rarity |
80 |
1/N on the chunk grid. Higher = rarer. |
min_chunk_distance |
16 |
Grid spacing in chunks. |
spread_salt |
0 |
Keep two dungeons off the same chunks. |
avoid_water |
true |
Skip water at the stand position. |
portal / portal.json| Field | Default | Notes |
|---|---|---|
activation |
catalyst if catalyst set, else always |
always / catalyst / key / both. |
frame |
minecraft:obsidian |
Shrine frame block. |
textures.portal |
minecraft:block/crying_obsidian |
Atlas sprite on the portal faces. |
color |
#5B21B6 |
Tint #RRGGBB. |
size.width / height |
4 / 5 |
Frame size. |
catalyst |
none | Item id string, or { "item", "count", "consume", "nbt" }. |
sound |
block.end_portal.spawn |
On enter. |
dimension |
customdungeon:dungeon |
Instance destination. |
return_portal |
true |
Exit portal inside the instance. |
Unbound portal: sneak-use a key with NBT Dungeon to bind it.
entry| Field | Default | Notes |
|---|---|---|
methods |
command, key, portal |
Subset of those three. |
key_item |
customdungeon:dungeon_key |
|
consume_key |
true |
|
require_key_nbt |
false |
Key NBT Dungeon must match. |
max_players |
8 |
Per instance. |
cooldown_seconds |
0 |
Per player. |
permission_level |
0 |
Vanilla permission (2 = op). |
required_advancement |
none | |
required_scoreboard / required_score |
unused | |
creative_bypass |
true |
Creative skips method / catalyst / cooldown. |
shared |
false |
Reuse a running instance. |
instance| Field | Default | Notes |
|---|---|---|
dimension |
portal dimension | Must exist. |
origin_y |
64 |
Build Y in the instance world. |
padding |
24 |
Bounds around rooms. |
reset_on_complete / empty / fail |
true |
Tear down the instance. |
idle_timeout_seconds |
600 |
Empty timeout. |
extract_seconds |
30 |
Victory countdown before teleport. 0 = immediate. |
layout| Field | Default | Notes |
|---|---|---|
type |
inferred | shape / linear / grid / free / single. |
start_room |
first room | Spawn room. |
corridor_width / height |
3 / 3 |
Walkable air. |
gap |
5 |
Air between procedural rooms. |
floor_gap |
gap |
Vertical air between stacked floors. |
corridor_block |
minecraft:stone_bricks |
Also corridor_floor / wall / ceiling. |
rooms[].id |
Local id. | |
rooms[].template |
same as id |
Room file name. |
rooms[].encounters |
[] |
Encounter ids. |
rooms[].next |
[] |
Extra corridor targets. |
rooms[].x / y / z |
Exact offset (or offset: {x,y,z}). |
rooms/<id>.json| Field | Default | Notes |
|---|---|---|
style |
none | Preset: crypt, nether, library, prison, sewer, end, jungle, ice, sand, … |
shape |
box |
box, circle, oval, cross, ring, diamond. |
size |
{x:13,y:7,z:13} |
Procedural only. SNBT size comes from the file. |
palette |
stone bricks | floor, wall, ceiling, accent, door, light, pillar. |
features |
style preset | See below. |
loot |
[] |
Chest loot table ids. |
constraints |
none | Effects while standing in this room. |
ladders |
true |
Vertical shafts between stacked floors. false on a room skips the whole link. |
snbt / snbt_file / structure |
none | Structure room instead of procedural. |
features: pillars, torches, windows, chest_count, carpet, fountain, cobwebs, skulls, bones, bookshelves, braziers, altar, hanging_lights, cages, vines, lava_moat, water_moat, floor_pattern (spots, checker, mosaic, path, rings, cracked, bones).
On rules (whole run) or a room. Reapplied while inside, cleared on leave. Room effects stack.
Booleans: slowness, mining_fatigue, weakness, hunger, wither, poison, glowing, nausea, darkness (blindness on 1.16). Amplifiers: slowness_level, mining_level, wither_level. Extra list: "effects": [{ "id": "minecraft:wither", "amplifier": 0, "duration": 80, "particles": true }].
encounters/<id>.json| Field | Default | Notes |
|---|---|---|
trigger |
enter |
Player steps into the room. |
trigger_delay_ticks |
20 |
Wait before the first wave. |
waves |
[] |
{ "delay_ticks", "mobs": [ … ] }. |
boss |
none | After waves; room waits until tagged mobs die. |
Mob spec: entity, count (number or {min,max}), name, health, damage, nbt, glowing, loot_table, equipment.helmet / chestplate / leggings / boots / mainhand.
rules| Field | Default | Notes |
|---|---|---|
time_limit_seconds |
0 |
0 = none. |
keep_inventory |
true |
|
pvp |
false |
|
allow_break / allow_place |
false |
Else only the allow-lists. |
allow_interact |
true |
|
allowed_break_blocks / allowed_place_blocks |
[] |
|
mob_griefing |
false |
|
difficulty |
inherit |
Or peaceful / easy / normal / hard. |
mob_health_multiplier / mob_damage_multiplier / player_damage_multiplier |
1.0 |
|
respawn_in_dungeon |
true |
false = leave on death. |
max_deaths |
0 |
0 = unlimited. |
drop_mob_loot |
true |
|
prevent_sleep |
true |
|
constraints |
none | Dungeon-wide effects. |
rewardson_complete / on_fail / on_room_clear: loot_table, xp, commands, broadcast, message, item_count.
config/customdungeon-common.toml
| Key | Default | Notes |
|---|---|---|
general.world_gen |
true |
Natural shrines / embeds. |
general.debug_logs |
false |
|
general.max_active_instances |
32 |
0 = unlimited. |
general.instance_spacing |
512 |
Gap between instances. |
general.instance_origin_y |
64 |
Fallback Y. |
general.allow_config_overrides |
true |
Load config/customdungeon/dungeons/**. |
general.protect_dungeon_blocks |
true |
Enforce break / place rules. |
general.default_world_gen_chance |
80 |
Fallback rarity. |
/cd start example_crypt
/cd start example_nether
/cd start example_end
/cd place example_crypt
Crypt portal: bound key + stone. Nether / End: explore new chunks in that dimension.