Biome Terrain Generation
Define a biome's actual terrain — surface layers, cave rock, or sky island shape — plus its climate range, ores, and structures.
This is the single file that defines a biome — one file per biome. It sets how the biome generates (terrain layers or fill blocks, climate range for biome selection, and which ores/structures/static objects/underground features can appear in it) and carries the optional client-side presentation for that biome (ambient particles and a shader override). Registering the biome — so the client and server agree on its ID — is implicit: the file’s presence in one of the fixed folders below is the registration; there is no separate biome catalog file. Every biome lives in exactly one of the three folders, matching the world type(s) it’s used in.
File Location
Unlike other catalog files, biome terrain definitions are not referenced from your mod’s manifest — every YAML file in these fixed folders is scanned and loaded automatically, one file per biome:
mods/<YourMod>/biomes/surface/<name>.yaml — for Default world builder presets
mods/<YourMod>/biomes/cave/<name>.yaml — for Cave world builder presets
mods/<YourMod>/biomes/sky-island/<name>.yaml — for Sky Island world builder presets (and Default's sky island overlay)
The name inside each file (not the file name) is the biome’s identity — what other config (World Builder Configuration’s biomes list, Sky Island Feature Configuration’s biomes list, Ore/Structure config’s implicit biome association) references, and what the client and server use to agree on the biome’s ID. Because the biome is defined in one place, there’s nothing to keep in sync — the name only needs to be consistent between this file and the config that references it.
A malformed optional field degrades independently to its own default without affecting the rest of the biome — but a missing/wrong-typed required field (noted per-type below) fails that entire biome file, and it won’t register at all.
Surface Biome
Used by the Default World Builder. Generates full terrain: altitude from one or more terrain generators, subsurface block layers, an optional surface fill (e.g. for shallow water), and biome weather.
Minimal Example
name: my_biome
type: surface
terrain-generators:
- type: builtin_simplex_noise
name: my_biome
min-altitude: 5
max-altitude: 30
noise-scale: 0.01
ground-layer-noise-scale: 0.01
surface-block: YourMod:my_grass
ground-layers:
- block-layers:
layer-0: YourMod:my_dirt_wall
layer-1: YourMod:my_dirt
min-thickness: 4
max-thickness: 7
Full Field Reference
name: my_biome # Required
type: surface
ground-layer-noise-scale: 0.01 # Required. Ground-layer thickness noise scale (not placement)
surface-block: YourMod:my_grass # Required. Top-most block
terrain-generators: # Required, at least one. See Terrain Generators below
- type: builtin_simplex_noise
name: my_biome
min-altitude: 5
max-altitude: 30
noise-scale: 0.01
ground-layers: # Required, at least one valid entry
- block-layers:
layer-0: YourMod:my_dirt_wall
layer-1: YourMod:my_dirt
min-thickness: 4
max-thickness: 7
ores: # Optional
- YourMod:my_ore
structures: # Optional
- YourMod:my_structure
static-object-spawns: # Optional
- YourMod:my_tree
underground-features: # Optional
- YourMod:my_feature
max-cave-spawn-altitude: 2147483647 # Optional. Default: i32::MAX (no limit)
height-blending-range: 10 # Optional. Default: 10
height-combination-mode: max # Optional. `max` or `add`. Default: max
min-temperature: 0.0 # Optional. Default: 0.0
max-temperature: 1.0 # Optional. Default: 1.0
min-precipitation: 0.0 # Optional. Default: 0.0
max-precipitation: 1.0 # Optional. Default: 1.0
min-altitude: -2147483648 # Optional. Default: i32::MIN (unbounded)
max-altitude: 2147483647 # Optional. Default: i32::MAX (unbounded)
fill-surface-blocks: # Optional, but required-if-present (see below)
fill-to-altitude: -5
block-layers:
layer-0: YourMod:my_wall_fill
layer-1: YourMod:my_water
default-weather: sunny # Optional. Default: Clear (unnamespaced)
weather-options: # Optional
- name: sunny
weight: 0.7
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | The biome’s identity, referenced by other config and used for client/server ID agreement. |
type | Yes | — | Must be surface, matching the folder the file is in. A mismatch or a missing type fails the biome at load with a message naming the folder it belongs in — it exists so a misfiled biome reports that once, instead of failing key-by-key against the wrong schema. |
ground-layer-noise-scale | Yes | — | Horizontal sampling scale for ground-layers thickness variation — lower values make each stratum’s thickness change more gradually across x. It affects nothing else: not where the biome is placed (that’s min/max-temperature and min/max-precipitation), and not the shape of its terrain (that’s each generator’s own noise-scale). |
surface-block | Yes | — | The top-most block placed at the biome’s altitude. |
terrain-generators | Yes | — | One or more altitude generators — see Terrain Generators. At least one must parse successfully or the whole biome fails. |
ground-layers | Yes | — | Subsurface block strata, each a noise-sampled thickness below the surface (not an altitude) — see Ground Layers. At least one valid entry is required. |
ores | No | (none) | Ore names (from Ore Configuration) enabled in this biome. |
structures | No | (none) | Structure names (from Structure Configuration) enabled in this biome. |
static-object-spawns | No | (none) | Names of registered trees/interactables that can spawn in this biome. A tree can equally name this biome from its own biomes field — the two lists are additive, and that’s the direction another mod has to use to add a tree here. |
underground-features | No | (none) | Names of underground features that apply specifically within this biome (in addition to any world-builder-wide global-underground-features). |
max-cave-spawn-altitude | No | (no limit) | Caves only generate at or below this world-Y within this biome. |
height-blending-range | No | 10 | Smoothing radius (in blocks) averaged on both sides of a column to avoid hard terrain seams at biome boundaries. |
height-combination-mode | No | max | How multiple terrain-generators altitudes combine at a given x: max (highest generator wins) or add (sum together). |
min-temperature / max-temperature | No | 0.0 / 1.0 | The band this biome occupies on the world’s temperature axis, in °C, on a fixed −40…50 scale — see the note below. The defaults are almost never what you want; set both. |
min-precipitation / max-precipitation | No | 0.0 / 1.0 | The band this biome occupies on the world’s rainfall axis, in mm/year, on a fixed 0…3000 scale — see the note below. The defaults are almost never what you want; set both. |
min-altitude / max-altitude | No | unbounded | Hard altitude (world-Y) bounds this biome is restricted to. |
fill-surface-blocks | No | (none) | Fills a fixed water-line-style range unconditionally up to an altitude — see Fill Surface Blocks. If present, both its sub-fields are required or the whole biome fails. |
default-weather | No | Clear | Starting weather type. Unlike every other name field, the default value is not namespaced to your mod — only an explicit value you provide gets namespaced. |
weather-options | No | (none) | Weather types this biome can transition to — see Weather Options. |
particles | No | (none) | Client-only ambient particle emitter groups — see Client Presentation. |
shader | No | (none) | Client-only namespaced shader override for this biome’s blocks — see Client Presentation. |
ground-layer-noise-scaleand a generator’snoise-scaleare different settings. The biome-level one scales the thickness noise forground-layers; each terrain generator has its ownnoise-scalethat shapes the surface altitude. The shippedplains.yamlsets both to0.01, which used to make them look like one duplicated value — they aren’t, and tuning one does nothing to the other.Renamed. This field used to be spelled
noise-scale(and before that,frequency-modifier). Sitting bare at the top of a file that already contained per-generatornoise-scalekeys, it read as the biome’s main noise setting and was neither that nor its placement — everywhere else in the schema anoise-scaleconfigures the noise of the block it sits in (an ore’s, a pool’s, a grid’s, a generator’s), and this was the one that reached past itself. A biome file still on the old key is rejected at load with a message naming the new one. Elsewhere,noise-scaleon a pool, underground feature or grid is unchanged and still means that thing’s own noise.
Temperature is °C and precipitation is mm of annual rainfall, on a fixed world-wide scale:
Axis Range temperature−40 … 50 °C precipitation0 … 3000 mm A biome declares the absolute band it occupies, and a column is placed into whichever biome’s box contains its sampled
(temperature, precipitation)point. The scale does not move: your desert at25–45°C stays exactly where you put it no matter which other biomes are loaded — including ones added later by another mod. Three consequences worth knowing:
- Give every biome an explicit range, and make the ranges tile the axes. Both default to
0.0/1.0, which on this scale is a sliver of cold, bone-dry climate — almost certainly not what you meant. A column whose point lands in no biome’s box falls back to the preset’sdefault-biomerather than erroring, so a biome with a mis-set band fails quietly.- A band outside the range is reported at load. One lying entirely outside can never be sampled (nothing generates it); one hanging over an edge is clipped, making the biome rarer than its numbers suggest. Both log a warning naming the biome and the range.
- Sky island biomes use a different scale — normalized
0.0–1.0, sampled by their feature rather than by this map. Don’t copy a band between the two.
Changed — this used to be relative. The engine previously stretched a noise field across the combined range of every loaded biome and then normalized straight back out, so the two cancelled and only each biome’s position relative to the others had any effect; the °C-looking values were decorative. The bad part was that adding a biome moved all the others — a mod shipping one hot desert silently shrank every existing biome’s share of the world. The frame is now fixed, which is what makes the units real and lets a mod add a biome without disturbing anyone else’s.
Terrain Generators
Each entry in terrain-generators dispatches on type:
builtin_simplex_noise — altitude from 2D Simplex noise:
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | Generator identifier (namespaced). Missing/wrong-typed fails the whole biome. |
min-altitude / max-altitude | No | 0 each | Altitude range this generator produces. |
noise-scale | No | 1.0 | Noise sampling scale — lower values produce larger terrain features. |
noise-transform-expression | No | (none) | An expression string for a custom altitude curve. Present-but-invalid fails the whole biome. |
builtin_simplex_noise_with_mask — like the above, but only active where a second noise field (Fbm/fractal Brownian motion) passes a threshold, letting a feature (e.g. a mesa spike) appear only in some areas:
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | Generator identifier (namespaced). Missing/wrong-typed fails the whole biome. |
min-altitude / max-altitude | No | 0 each | Altitude range this generator produces where active. |
mask-noise-scale | No | 1.0 | Sampling scale of the mask noise field. |
noise-scale | No | 1.0 | Sampling scale of the altitude noise field. |
mask-value-activation | No | 0.0 | Mask noise must exceed this value for the generator to be active at that x; elsewhere it contributes no altitude at all (not zero — simply absent from the combination). |
noise-transform-expression | No | (none) | Same as above. |
Noise Transform Expressions
noise-transform-expression is a small formula string evaluated with the variables noise, x, scale (max-altitude - min-altitude), min_altitude, and max_altitude, letting you reshape the raw noise value into a custom altitude curve instead of the default linear noise * scale + min_altitude:
noise-transform-expression: clamp(noise * noise * 2.0, 0.0, 1.0) * scale + min_altitude
Ground Layers
Each entry maps a thickness range to a block-layers map of per-layer block names:
ground-layers:
- block-layers:
layer-0: YourMod:my_wall_block
layer-1: YourMod:my_block
min-thickness: 4
max-thickness: 7
| Field | Required | Default | Description |
|---|---|---|---|
block-layers.layer-0, block-layers.layer-1, … | No | Creation:air | Block placed on each numbered layer (nested under block-layers) within this range. |
min-thickness / max-thickness | Yes | — | Thickness range (in blocks below the surface, not world-Y) this layer entry fills. An entry missing either is skipped (only that entry, not the whole biome). |
Fill Surface Blocks
Unconditionally fills a range up to a fixed altitude regardless of terrain — used for a biome’s water table (e.g. ocean biomes):
fill-surface-blocks:
fill-to-altitude: -5
block-layers:
layer-0: YourMod:my_wall_fill
layer-1: YourMod:my_water
| Field | Required | Description |
|---|---|---|
fill-to-altitude | Yes | Fills up to (and including) this world-Y. |
block-layers | Yes, non-empty | Keyed layer-N map (layer-0, layer-1, …); an omitted layer defaults to Creation:air. Same shape as ground-layers’ block-layers. |
Weather Options
default-weather: sunny
weather-options:
- name: sunny
weight: 0.7
- name: rainy
weight: 0.3
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | Weather type name. Missing on any one entry fails the whole biome. |
weight | No | 1.0 | Relative weight for this weather in the biome’s weighted pick-one — an option’s odds are its weight over the sum of the biome’s weather weights, not a probability. |
Cave Biome
Used by the Cave World Builder. There’s no surface or terrain layers — the biome is the rock type, filling every position solidly until caves are carved out of it.
Minimal Example
name: my_cave_biome
type: cave
fill-block: YourMod:my_stone
Full Field Reference
name: my_cave_biome # Required
type: cave
fill-block: YourMod:my_stone # Required. Solid rock (layer 1)
fill-wall-block: YourMod:my_wall # Optional. Wall block (layer 0). Falls back to AIR if unset
floor-block: YourMod:my_dirt # Optional. Replaces the top face of solid blocks under open cave space
ceiling-block: YourMod:my_stone # Optional. Replaces the bottom face of solid blocks over open cave space
ores: # Optional
- YourMod:my_ore
structures: # Optional
- YourMod:my_structure
static-object-spawns: # Optional
- YourMod:my_tree
underground-features: # Optional
- YourMod:my_feature
min-depth-factor: 0.0 # Optional. Default: 0.0. How deep this biome sits — see below
max-depth-factor: 1.0 # Optional. Default: 1.0
min-lateral-factor: 0.0 # Optional. Default: 0.0. Horizontal placement — see below
max-lateral-factor: 1.0 # Optional. Default: 1.0
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | The biome’s identity, referenced by other config and used for client/server ID agreement. |
type | Yes | — | Must be cave, matching the folder the file is in. A mismatch or a missing type fails the biome at load with a message naming the folder it belongs in — it exists so a misfiled biome reports that once, instead of failing key-by-key against the wrong schema. |
fill-block | Yes | — | Block filling every solid (layer 1) position this biome owns. |
fill-wall-block | No | (air) | Block filling wall (layer 0) positions. |
floor-block | No | (none) | Block substituted onto the top face of a solid block with open cave space directly above it. |
ceiling-block | No | (none) | Block substituted onto the bottom face of a solid block with open cave space directly below it. |
ores / structures / static-object-spawns / underground-features | No | (none) | Same meaning as the surface biome’s equivalents. |
min-depth-factor / max-depth-factor | No | 0.0 / 1.0 | The depth band this biome occupies, 0.0 (shallowest) to 1.0 (deepest). |
min-lateral-factor / max-lateral-factor | No | 0.0 / 1.0 | The horizontal band this biome occupies, on an axis that varies with X independently of depth. |
particles / shader | No | (none) | Client-only presentation, same as the surface biome — see Client Presentation. |
Floor/ceiling substitution happens after the main cave carving pass, so it only affects blocks actually adjacent to open cave space — not every solid block in the biome.
How cave biomes are placed
The generator samples two independent noise fields and picks the biome whose declared bands contain both values. The fields are deliberately biased:
- Depth factor varies mostly with Y. Give a biome
min-depth-factor: 0.6/max-depth-factor: 1.0and it only appears in the lower part of the cave layer;0.0–0.4keeps it near the surface. - Lateral factor varies mostly with X, so at any given depth it decides which of the biomes valid at that depth you get as you travel sideways.
Together they form a grid: split the depth axis into bands for “how deep”, and the lateral axis into bands for “which variant”. Two biomes that overlap on both axes are chosen between by a third noise field, so overlap is allowed and produces mixing rather than one biome winning outright.
Sky Island Biome
Used by the Sky Island World Builder, and by any sky island feature referenced from a Default builder’s sky-island-features overlay.
Minimal Example
name: my_island_biome
type: sky-island
fill-block: YourMod:my_dirt
surface-block: YourMod:my_grass
Full Field Reference
name: my_island_biome # Required
type: sky-island
fill-block: YourMod:my_dirt # Required. Interior solid block (layer 1)
surface-block: YourMod:my_grass # Required. Top exposed face
fill-wall-block: YourMod:my_wall # Optional. Wall block (layer 0). Falls back to AIR if unset
underside-block: YourMod:my_stone # Optional. Bottom exposed face
ores: # Optional
- YourMod:my_ore
underground-features: # Optional
- YourMod:my_feature
min-temperature: 0.0 # Optional. Default: 0.0
max-temperature: 1.0 # Optional. Default: 1.0
min-precipitation: 0.0 # Optional. Default: 0.0
max-precipitation: 1.0 # Optional. Default: 1.0
Note: unlike surface and cave biomes, a sky island biome does not drive its own
structuresorstatic-object-spawns— those are declared on the sky island feature that references this biome. Writing either key here is a load-time error that skips the biome, the same as any other unrecognized key, rather than a setting that quietly does nothing. Onlyoresandunderground-featuresare biome-level for sky islands.
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | The biome’s identity, referenced by other config and used for client/server ID agreement. |
type | Yes | — | Must be sky-island, matching the folder the file is in. A mismatch or a missing type fails the biome at load with a message naming the folder it belongs in — it exists so a misfiled biome reports that once, instead of failing key-by-key against the wrong schema. |
fill-block | Yes | — | Block filling the island’s solid interior (layer 1). |
surface-block | Yes | — | Block placed on the top exposed face of the island. |
fill-wall-block | No | (air) | Wall (layer 0) block. Falls back to AIR — correct for floating islands, which have no back wall. |
underside-block | No | (none) | Block placed on the bottom exposed face of the island. |
ores / underground-features | No | (none) | Same meaning as the surface biome’s equivalents. structures and static-object-spawns are not accepted here — see the note above; declare them on the sky island feature instead. |
min-temperature / max-temperature / min-precipitation / max-precipitation | No | 0.0 / 1.0 each | Climate range used to select among a feature’s registered biomes. Unlike a surface biome’s °C/mm bands, these are normalized 0.0–1.0 coordinates sampled by the owning feature, not by the surface climate map. Inert when a feature registers only one biome (the single biome is chosen without sampling climate). |
particles / shader | No | (none) | Client-only presentation, same as the surface biome — see Client Presentation. |
Warning: a sky island biome used as a feature’s or preset’s
default-biomestill needs its own file inbiomes/sky-island/like any other biome — a biome the client has never loaded produces ID0, which the client doesn’t recognize, showing as “no biome” in-game.
Client Presentation: Particles & Shader
particles and shader are client-only optional fields — the server ignores them, so they’re valid in any of the three biome types above. They control how the biome looks, not how it generates.
Shader
shader: YourMod:my_biome_shader
A namespaced shader name to render this biome’s blocks with, overriding the default block shader. See Shader Configuration.
Particles
Each entry in particles is one independent ambient-particle group — a biome can have multiple groups, each triggering under different conditions:
particles:
- emit-random:
- name: YourMod:my_dust_particle
chance: 0.1
cooldown-ms: 100
lifetime-ms: 1000
x-offset-min: -0.5
x-offset-max: 0.5
y-offset-min: 0.0
y-offset-max: 0.5
valid-blocks:
- YourMod:air
block-spawn-source: world_generation
min-altitude: 0
max-altitude: 100
| Field | Default | Description |
|---|---|---|
emit-random | (required) | A list of particle emitters to randomly trigger — see Emit Random below. |
valid-blocks | (required, can be empty) | Block names this group can emit near. An empty list matches any block. |
block-spawn-source | (required) | Which placement origin the block must have for this group to trigger: world_generation, structure_generation, player_interaction, or mob_interaction. |
min-altitude / max-altitude | unbounded | The world-Y range this group is restricted to. |
Emit Random
Each entry in emit-random references a particle registered in particle-config.yaml and controls how often it randomly spawns:
| Field | Default | Description |
|---|---|---|
name | (required) | The particle to spawn, from particle-config.yaml. |
chance | 0.1 | Probability (0.0–1.0) checked each time this emitter is eligible to fire. |
cooldown-ms | 1000 | Minimum time between spawn attempts for this emitter. |
lifetime-ms | 1 | How long the spawned particle lives. |
has-lifetime | true | Whether the particle expires after lifetime-ms at all. |
x-offset-min / x-offset-max | 0.0 each | Random horizontal offset range from the triggering block. |
y-offset-min / y-offset-max | 0.0 each | Random vertical offset range from the triggering block. |
Complete Examples
Based on the real shipped biomes.
Surface with ambient particles (biomes/surface/forest.yaml — shows client-only particles living alongside terrain generation):
name: forest
type: surface
terrain-generators:
- type: builtin_simplex_noise
name: forest
min-altitude: 5
max-altitude: 30
noise-scale: 0.01
ground-layer-noise-scale: 0.01
surface-block: grass
ground-layers:
- block-layers:
layer-0: dirt_wall
layer-1: dirt
min-thickness: 4
max-thickness: 7
- block-layers:
layer-0: stone_wall
layer-1: stone
min-thickness: 700
max-thickness: 800
ores:
- coal_ore
min-temperature: 5
max-temperature: 20
min-precipitation: 800
max-precipitation: 2000
default-weather: sunny
weather-options:
- name: sunny
weight: 0.6
static-object-spawns:
- oak_tree
particles:
- emit-random:
- name: purple_spec
chance: 0.1
cooldown-ms: 100
lifetime-ms: 1000
x-offset-min: -0.5
x-offset-max: 0.5
y-offset-min: 0.0
y-offset-max: 0.5
valid-blocks:
- air
block-spawn-source: world_generation
min-altitude: 0
max-altitude: 100
Surface (biomes/surface/mesa.yaml — exercises both terrain generator types):
name: mesa
type: surface
height-blending-range: 3
terrain-generators:
- type: builtin_simplex_noise
name: mesa_ground
min-altitude: 5
max-altitude: 8
noise-scale: 0.01
- type: builtin_simplex_noise_with_mask
name: mesa_mask
min-altitude: 10
max-altitude: 50
mask-noise-scale: 0.01
noise-scale: 0.01
noise-transform-expression: clamp(noise * noise * 2.0, 0.0, 1.0) * scale + min_altitude
mask-value-activation: 0.2
ground-layer-noise-scale: 0.01
surface-block: red_sand
ground-layers:
- block-layers:
layer-0: dirt_wall
layer-1: red_sand
min-thickness: 12
max-thickness: 24
- block-layers:
layer-0: stone_wall
layer-1: stone
min-thickness: 1500
max-thickness: 1500
ores:
- coal_ore
structures:
- bush
- base
min-temperature: 20
max-temperature: 35
min-precipitation: 200
max-precipitation: 600
default-weather: sunny
weather-options:
- name: sunny
weight: 0.8
- name: rainy
weight: 0.2
Surface with a surface fill (biomes/surface/tropical_ocean.yaml):
name: tropical_ocean
type: surface
terrain-generators:
- type: builtin_simplex_noise
name: tropical_ocean
min-altitude: -40
max-altitude: 10
noise-scale: 0.01
ground-layer-noise-scale: 0.01
surface-block: sand
ground-layers:
- block-layers:
layer-0: dirt_wall
layer-1: sand
min-thickness: 5
max-thickness: 7
- block-layers:
layer-0: stone_wall
layer-1: stone
min-thickness: 700
max-thickness: 800
ores:
- coal_ore
min-temperature: 24
max-temperature: 30
min-precipitation: 1500
max-precipitation: 3000
max-cave-spawn-altitude: -30
fill-surface-blocks:
fill-to-altitude: -5
block-layers:
layer-0: dirt_wall
layer-1: water
default-weather: sunny
weather-options:
- name: sunny
weight: 0.7
- name: rainy
weight: 0.3
Cave (biomes/cave/cave_shallow.yaml):
name: cave_shallow
type: cave
fill-block: stone
fill-wall-block: stone_wall
floor-block: dirt
ceiling-block: dirt
ores:
- coal_ore
structures:
- base
- base_air
static-object-spawns:
- cherry_tree
min-depth-factor: 0.0
max-depth-factor: 0.4
min-lateral-factor: 0.0
max-lateral-factor: 0.5
Sky Island (biomes/sky-island/meadow_island.yaml):
name: meadow_island
type: sky-island
fill-block: dirt
surface-block: grass
underside-block: stone
ores:
- coal_ore
underground-features:
- island_hollow
min-temperature: 0.0
max-temperature: 1.0
min-precipitation: 0.0
max-precipitation: 1.0