Fourteen settings in config/crawlspace-server.toml,
in three groups. Worldgen reads them live, so a change applies to chunks generated afterwards; dungeons
already in the world stay where they are. Then the datapack side: reskin a theme, change its monsters and
boss, add an entrance style for a biome - and the API an RPG mod plugs its dice into.
[worldgen]
Spacing is config rather than datapack data, because vanilla's structure placement is the only kind
/locate searches, and CrawlSpace extends it. A dungeon is up to fifteen chunks across.
| Setting | Default | What it does |
|---|---|---|
| enabled | true | Generate dungeons in new chunks. |
| spacing | 36 8-512 | Average distance between dungeons, in chunks: one per spacing-by-spacing square. Dungeon Crawl uses 32 and villages 34; 36 keeps them about as common as villages. |
| separation | 16 4-511 | Minimum distance between two dungeons, in chunks. Must be less than spacing. Below 16 two dungeons can overlap underground. |
| maxLevels | 6 1-9 | Levels below the entrance, at most. Fewer where the world is not deep enough. Themes follow the level number, so the Caverns (levels 7 and 8) and the Deep Halls (level 9) only appear above 6. |
| minLevels | 2 1-9 | Skip a site where fewer than this many levels fit above the bottom of the world. |
[play]
| Setting | Default | What it does |
|---|---|---|
| hints | AUTO AUTO · ALWAYS · NEVER | Tells for players without a perception skill: secret walls built from a related but different block, and faint particles near you - red for an unsprung trap, green for a secret door or treasure. AUTO is on unless a mod (LegendQuest, say) has registered its own perception checks; then that does the finding. |
| disarmChance | 0.75 0-1 | Without a perception mod: the chance that breaking a trap's plate or wire, or sneak-using it, disarms it rather than setting it off. A perception mod rolls its own instead. |
| spawnerUses | 24 0-100000 | How many monsters a dungeon's spawner makes before it burns out, so a dungeon is not a farm. 0: spawners never burn out. |
| spawnersIgnoreLight | true | A dungeon's spawners keep spawning in light, so a torch on one does not switch it off. Only spawners inside a dungeon, and there must still be room for the monster. Off: vanilla rules. |
| eventSeconds | 45 0-3600 | The dungeon clock: every this many seconds, each level with a player on it rolls a die, and on a 1 something happens. Fighting makes noise: for a while after, a 2 counts too. 0 turns events off. |
| restockHours | 12 0-8760 | Hours of real time before a dungeon restocks: its rooms fill with monsters again and its chests refill as they are next opened. Never while anyone else is inside; it happens as someone arrives. Lootr's chests refill by Lootr's own rules. 0: dungeons never restock. |
[protection]
In survival the dungeon's shell will not break, and hitting it says so: "The dungeon's stonework holds. Find another way." Creative is unaffected, and so is anything a player placed.
| Setting | Default | What it does |
|---|---|---|
| enabled | true | Keep the dungeon whole: players in survival cannot break its walls, floors, ceilings, stairs, tower, locked doors or puzzle rooms. Dressing still breaks - chests, spawners, pots, cobwebs, furniture, wooden doors - as do trap plates. Off: dungeons are ordinary blocks, minable like the rest of the world. |
| explosions | true | With protection on: creepers and TNT still hurt, and still break the dressing, but not the shell. |
| repair | true | With protection on: put back any shell block found missing near a player, every few seconds. Catches machines and mods that remove blocks without the usual break event - drills, lasers, tunnellers. Pistons cannot move the shell either way. |
Datapacks
/crawlspace export writes the built-in themes and entrance styles out as a datapack
to start from, and the example datapack on the GitHub release shows the shape. Two registries:
data/<namespace>/crawlspace/theme/ and
data/<namespace>/crawlspace/entrance/.
A theme is its blocks (a weighted wall list, the floor, the carpet, which pressure plate a trap uses), a weighted list of the mobs its rooms wake, and its boss: the mob, the name over the bar, the weapon, and the bar's colour. Ship a file at the built-in theme's own path to replace it.
// data/crawlspace/crawlspace/theme/crypt.json (same path as the built-in one: replaces it)
{
"blocks": {
"wall": [
{ "block": "minecraft:sandstone", "weight": 60 },
{ "block": "minecraft:cut_sandstone", "weight": 25 },
{ "block": "minecraft:chiseled_sandstone", "weight": 15 }
],
"floor": "minecraft:smooth_sandstone",
"carpet": "minecraft:orange_carpet",
"trap_plate": "minecraft:birch_pressure_plate"
},
"mobs": [
{ "type": "minecraft:husk", "weight": 4 },
{ "type": "minecraft:skeleton", "weight": 3 },
{ "type": "minecraft:cave_spider", "weight": 1 }
],
"boss": { "type": "minecraft:husk", "name": "the Dune King", "weapon": "minecraft:golden_sword", "bar": "yellow" }
}
An entrance style claims biomes - ids or #tags -
and says what the tower is built from: the wall list, the top, the trim, the stair and the roof, plus
weights for the four designs (keep, round,
pyramid, temple). Leave a design out and it is never built
there.
// data/example/crawlspace/entrance/basalt.json (a new style, for the biomes it names)
{
"biomes": ["minecraft:basalt_deltas", "#minecraft:is_badlands"],
"blocks": {
"wall": [
{ "block": "minecraft:polished_basalt", "weight": 3 },
{ "block": "minecraft:basalt", "weight": 1 }
],
"top": "minecraft:blackstone",
"trim": "minecraft:polished_blackstone",
"stair": "minecraft:polished_blackstone_stairs",
"roof": "minecraft:blackstone"
},
"designs": { "keep": 1, "round": 3 }
}
Loot is ordinary datapack loot tables -
crawlspace:chests/tier1 to tier5 by depth, and
supplies - so a pack overrides them the vanilla way.
The layout is not data, deliberately: the planner's room shapes, corridor styles and heights per theme are code, which is what lets the build plan thousands of dungeons in seconds and prove every one is sealed. What a datapack changes is what it is built from and what lives in it.
The Perception API
One door for other mods: CrawlSpaceApi.setPerception(Perception). An RPG mod
registers once, and from then on CrawlSpace asks it who notices what, with the dungeon level as the
difficulty. Last one in wins. CrawlSpace never imports the mod that provides it, and LegendQuest is
just the first to.
CrawlSpaceApi.setPerception(new Perception() {
public boolean notices(ServerPlayer player, Hidden what, int depth) { /* TRAP or SECRET_DOOR */ }
public boolean disarms(ServerPlayer player, int depth) { ... }
// the rest are optional, and default to "no":
public boolean recovers(ServerPlayer player, int depth) { ... } // stepping off a puzzle path
public boolean spotsMimic(ServerPlayer player, int depth) { ... }
public boolean disarmsChest(ServerPlayer player, int depth) { ... }
public boolean readsTell(ServerPlayer player, int depth) { ... }
public boolean readsOmen(ServerPlayer player, int depth) { ... }
public boolean evades(ServerPlayer player, int depth) { ... } // a sentry's eye
}); | Hook | Asked when |
|---|---|
| notices | A player first comes within a few blocks of a hidden trap or secret door - once per player per thing. Noticed, it is shown to them from then on. |
| disarms | A player sneaks and uses a trap they have spotted. A failure springs it on them. |
| recovers | A player touches the void off a puzzle path, or stands on a pit as it gives way. A pass puts them back on the last block they stood on. |
| spotsMimic | A player first opens a chest that is a mimic. A pass warns them and the chest stays shut; opening it again is their choice. |
| disarmsChest | A player opens a trapped chest. A pass draws the needle and the trap never springs. |
| readsTell | A player comes near a trap's tell - once per player per tell. A pass says what it warns of; without an answer the tell is still there to read by eye. |
| readsOmen | A player comes near a shrine. A pass says which shrine it is, and whether it is cursed. |
| evades | A sentry would first see a player. A pass, and that sentry never sees them. |
With no Perception registered, hints and disarmChance above
do the job for everyone. The last six hooks have defaults, so a mod written against the first two keeps
working, and whatever it does not answer is simply a no.