Features & carvers

The worldgen decoration layer: the shared value-provider building blocks, configured features (the shapes) and placed features (where/how often they appear), and configured carvers that cut caves and canyons. Primary syntax targets 1.21+ (singular worldgen/configured_feature/, worldgen/placed_feature/, worldgen/configured_carver/ folders).

Shared building blocks

Several small value types appear across features, carvers, and structures. The dossier factors them out once; every schema below refers back to them. Wherever a field is typed as "vertical anchor", "height provider", "int provider", "float provider", or "block state provider", plug in one of the objects defined here.

Vertical anchor

A single Y position relative to the world. Use exactly one key.

KeyMeaning
absoluteA literal Y value.
above_bottomY = minimum build height + n.
below_topY = maximum build height − n (should not be negative).

vertical anchor β€” the three forms

{ "absolute": 0 }
{ "above_bottom": 8 }
{ "below_top": 10 }

Height provider

Returns a Y using vertical anchors. Used for ore height ranges, carver origins, and structure start heights.

TypeFields
constantvalue (vertical anchor) β€” may also be given as a bare anchor object.
uniformmin_inclusive, max_inclusive (anchors).
biased_to_bottommin_inclusive, max_inclusive, optional inner (default 1).
very_biased_to_bottommin_inclusive, max_inclusive, optional inner.
trapezoidmin_inclusive, max_inclusive, optional plateau (flat middle length).
weighted_listdistribution: list of { "data": <height provider>, "weight": <int> }.

height provider β€” two forms

{ "type": "uniform", "min_inclusive": { "absolute": 0 }, "max_inclusive": { "absolute": 256 } }
{ "type": "trapezoid", "min_inclusive": { "above_bottom": 5 }, "max_inclusive": { "below_top": 10 }, "plateau": 20 }

Int provider & float provider

An int provider returns an integer for numeric parameters (vein size, patch tries, radii). A float provider mirrors it with constant / uniform / clamped_normal / trapezoid types and is used for carver radii.

TypeFields
constantvalue (int) β€” may be given as a bare int.
uniformmin_inclusive, max_inclusive (ints, max ≥ min).
biased_to_bottommin_inclusive, max_inclusive.
clampedsource (int provider), min_inclusive, max_inclusive.
clamped_normalmean (float), deviation (float), min_inclusive, max_inclusive.
weighted_listdistribution: list of { "data": <int provider>, "weight": <int> }.

int provider β€” two forms

{ "type": "uniform", "min_inclusive": 0, "max_inclusive": 7 }
{ "type": "clamped_normal", "mean": 8.0, "deviation": 3.0, "min_inclusive": 1, "max_inclusive": 16 }

Block state provider

Decides which block state to place at each position inside a feature (trunks, foliage, patches, disks). Wherever a feature field is typed "block state provider", use one of these.

TypeFields
simple_state_provider (a.k.a. simple)state (block state).
weighted_state_providerentries[]: { "data": <block state>, "weight": <int> } (non-empty).
noise_providerseed (long), noise (noise params), scale (float > 0), states[].
noise_threshold_providerseed, noise, scale, threshold (−1..1), high_chance (0..1), low_states[], high_states[], default_state.
dual_noise_provideras noise_provider plus slow_noise, slow_scale, variety ([min,max] 1–64).
randomized_int_state_providerproperty (block property name), values (int provider), source (block state provider).
rotated_block_providerstate (block state) β€” randomizes axis / facing.

The noise field is a noise-parameters object (firstOctave + amplitudes[]), not an empty object β€” e.g. { "firstOctave": -3, "amplitudes": [1.0] }.

worldgen/placed_feature examples reuse these β€” weighted logs, then randomized crop age

{
  "type": "weighted_state_provider",
  "entries": [
    { "data": { "Name": "minecraft:oak_log", "Properties": { "axis": "y" } }, "weight": 3 },
    { "data": { "Name": "minecraft:birch_log", "Properties": { "axis": "y" } }, "weight": 1 }
  ]
}
{
  "type": "randomized_int_state_provider",
  "property": "age",
  "values": { "type": "uniform", "min_inclusive": 0, "max_inclusive": 7 },
  "source": { "type": "simple_state_provider", "state": { "Name": "minecraft:wheat" } }
}
🎩 Trick

noise_provider / dual_noise_provider create smooth patchy block variation (e.g. mixed grass/podzol) instead of per-block randomness. randomized_int_state_provider is how crops and berries generate at random growth ages.

πŸ“Œ Note

Generation step (GenerationStep.Decoration). Placed features and structures are ordered into a shared, per-chunk decoration enum, stable since 1.18: raw_generation, lakes, local_modifications, underground_structures, surface_structures, strongholds, underground_ores, underground_decoration, fluid_springs, vegetal_decoration, top_layer_modification. A feature in an earlier step sees the world before later steps have run. (Placed features receive their step from the biome that lists them, not from the placed-feature JSON.)

Configured features

A configured feature at data/<namespace>/worldgen/configured_feature/ is a feature type bundled with its config. It never generates by itself β€” a placed feature references it and supplies the placement rules, or a biome references it. Root shape:

worldgen/configured_feature β€” root schema shape

{
  "type": "minecraft:<feature_id>",
  "config": { /* type-specific */ }
}

/place feature <configured_feature_id> [pos] places one directly for testing β€” it resolves against the configured_feature registry, not the placed-feature registry, and ignores placement modifiers.

Common feature types

CategoryTypes
Vegetationtree, flower, no_bonemeal_flower, random_patch, simple_random_selector, random_selector, random_boolean_selector, bamboo, sea_pickle, kelp, seagrass, vines, waterlogged_vegetation_patch, vegetation_patch, multiface_growth, sculk_patch, twisting_vines, weeping_vines
Terrain / blobsore, disk, lake, spring_feature, block_pile, delta_feature, iceberg, basalt_columns, basalt_pillar, netherrack_replace_blobs, fill_layer, geode, replace_single_block
Structures-in-featuresfossil, desert_well, monster_room, huge_red_mushroom, huge_brown_mushroom, huge_fungus, nether_forest_vegetation
Blocks / columnsblock_column, simple_block, block_pile, coral_tree, coral_claw, coral_mushroom, glow_lichen, dripstone_cluster, pointed_dripstone, large_dripstone
Config-less (empty config)blue_ice, bonus_chest, chorus_plant, desert_well, end_island, end_platform, freeze_top_layer, kelp, monster_room, no_op, vines, void_start_platform, weeping_vines

tree

The most involved feature. It composes a trunk placer, a foliage placer, block state providers for logs/leaves/dirt, a minimum-size guard, and optional decorators. Schema shape (angle-bracket placeholders indicate where the building-block objects go):

worldgen/configured_feature β€” tree config shape

{
  "type": "minecraft:tree",
  "config": {
    "trunk_provider":   { /* block state provider β€” the log */ },
    "foliage_provider": { /* block state provider β€” the leaves */ },
    "trunk_placer":     { "type": "...", "base_height": 4, "height_rand_a": 2, "height_rand_b": 0 },
    "foliage_placer":   { "type": "...", "radius": <int provider>, "offset": <int provider> },
    "minimum_size":     { "type": "two_layers_feature_size", "limit": 1, "lower_size": 0, "upper_size": 1 },
    "dirt_provider":    { /* block state provider β€” block placed under trunk */ },
    "root_placer":      { /* optional */ },
    "decorators":       [ /* required, may be empty β€” tree decorators */ ],
    "ignore_vines":     false,
    "force_dirt":       false
  }
}

Trunk placers (all share numeric base_height, height_rand_a, height_rand_b):

TypeExtra fields
straight_trunk_placerβ€”
forking_trunk_placerβ€”
giant_trunk_placerβ€”
mega_jungle_trunk_placerβ€”
dark_oak_trunk_placerβ€”
fancy_trunk_placerβ€”
bending_trunk_placermin_height_for_leaves, bend_length
upwards_branching_trunk_placerextra_branch_steps, place_branch_per_log_probability, extra_branch_length, can_grow_through
cherry_trunk_placerbranch_count, branch_horizontal_length, branch_start_offset_from_top, branch_end_offset_from_top

Foliage placers (all take radius + offset int providers, plus extras):

TypeExtra fields
blob_foliage_placerheight
spruce_foliage_placertrunk_height
pine_foliage_placerheight
acacia_foliage_placerβ€”
bush_foliage_placerβ€”
fancy_foliage_placerheight
jungle_foliage_placerheight
mega_pine_foliage_placercrown_height
dark_oak_foliage_placerβ€”
random_spread_foliage_placerfoliage_height, leaf_placement_attempts
cherry_foliage_placerheight, wide_bottom_layer_hole_chance, corner_hole_chance, hanging_leaves_chance, hanging_leaves_extension_chance

Minimum size controls trunk width vs. height so the tree fits before it is placed:

TypeFields
two_layers_feature_sizelimit, lower_size, upper_size, optional min_clipped_height.
three_layers_feature_sizelimit, upper_limit, lower_size, middle_size, upper_size, optional min_clipped_height.

Decorators (tree decorators β€” the required decorators[] array):

DecoratorFields
trunk_vineβ€”
leave_vineprobability
cocoaprobability
beehiveprobability
alter_groundprovider (block state provider)
attached_to_leavesprobability, exclusion_radius_xz, exclusion_radius_y, required_empty_blocks, block_provider, directions
πŸ’‘ Best practice

Keep the tree's minimum_size in sync with the foliage_placer.radius. If foliage is wider than the reserved footprint it clips and the whole tree silently fails to place.

ore

Blob of ore blocks that replace matching targets. size is the vein size (int 0–64); discard_chance_on_air_exposure (float 0–1) is the per-block chance to skip a block adjacent to air (the "eaten by caves" look). Each targets[] entry is { target: <rule test>, state: <block state> }, where the rule test uses the same predicate grammar as processor rule tests (always_true, block_match, blockstate_match, tag_match, random_block_match, random_blockstate_match).

data/example/worldgen/configured_feature/ore_iron.json

{
  "type": "minecraft:ore",
  "config": {
    "size": 9,
    "discard_chance_on_air_exposure": 0.0,
    "targets": [
      { "target": { "predicate_type": "minecraft:tag_match", "tag": "minecraft:stone_ore_replaceables" },
        "state": { "Name": "minecraft:iron_ore" } },
      { "target": { "predicate_type": "minecraft:tag_match", "tag": "minecraft:deepslate_ore_replaceables" },
        "state": { "Name": "minecraft:deepslate_iron_ore" } }
    ]
  }
}

random_patch, disk, lake & geode

random_patch (and flower / no_bonemeal_flower) scatters a sub-feature. Note its feature field is a placed feature reference (or inline placed feature), not a configured one.

data/example/worldgen/configured_feature/flower_patch.json

{
  "type": "minecraft:random_patch",
  "config": {
    "tries": 96,
    "xz_spread": 7,
    "y_spread": 3,
    "feature": "example:placed_single_flower"
  }
}

disk β€” a flat blob (clay/sand/gravel patches):

FieldMeaning
state_providerAny block state provider for the disk blocks β€” a plain simple_state_provider or a rule_based_state_provider (both valid; see note).
radiusInt provider, 0–8.
half_heightInt provider, 0–4.
targetBlock predicate the disk may replace (vanilla uses matching_blocks).
πŸ“Œ JAR-verified (26.1.2-0.19.2)

disk.state_provider is a generic block state provider, not hardcoded to rule-based β€” confirmed against vanilla configured features by sibling elkonia-wob: disk_clay/disk_gravel use a plain simple_state_provider, while disk_sand/disk_grass use rule_based_state_provider (all four with target: matching_blocks). This is not a version change β€” the field has always accepted any provider; the vanilla sand/grass disks just happen to use the rule-based one.

lake β€” takes fluid (block state provider) and barrier (block state provider). A minimal example:

data/example/worldgen/configured_feature/lava_lake.json

{
  "type": "minecraft:lake",
  "config": {
    "fluid":   { "type": "simple_state_provider", "state": { "Name": "minecraft:lava" } },
    "barrier": { "type": "simple_state_provider", "state": { "Name": "minecraft:stone" } }
  }
}

geode β€” the amethyst-geode generator. Its config is large: blocks (filling, inner_layer, alternate_inner_layer, middle_layer, outer_layer providers), layers (thickness floats), crack (generate_crack_chance, base_crack_size, crack_point_offset), inner_placements, plus int providers outer_wall_distance / distribution_points / point_offset, and min_gen_offset, max_gen_offset, invalid_blocks_threshold, use_potential_placements_chance.

Two more terrain features worth their fields:

FeatureFields
spring_featurestate (fluid block state), rock_count (default 4), hole_count (default 1), requires_block_below (default true), valid_blocks (block id/tag/list).
fossilfossil_structures[] (NBT template ids), overlay_structures[] (same length), fossil_processors, overlay_processors, max_empty_corners_allowed (0–7).
block_columndirection (up/down/north/east/south/west), allowed_placement (block predicate), prioritize_tip (bool), layers[] of { height: <int provider>, provider: <block state provider> }.
delta_featurecontents (block state), rim (block state), size (int provider 0–16), rim_size (int provider 0–16).
⚠ Version differences
  • Since 1.21 (pack_format 48): folder is singular worldgen/configured_feature/.
  • Since 1.19: sculk_patch and multiface_growth (renamed from the glow_lichen feature) added.
  • Since 1.20: huge_fungus gained replaceable_blocks.
  • Since 1.21.4: simple_block gained optional schedule_tick.
πŸ“Œ Note

Tentative (26.x snapshots / pack_format ≥ 88, after 1.21.8): the registry worldgen/configured_feature is reported to become worldgen/feature with the config inlined into the root object (no separate config field), and geode block fields to accept ids/lists in addition to tags. This is forward-looking and unverified β€” do not apply it at a 1.21 baseline; confirm against the live wiki before relying on it.

🎩 Trick

Use random_selector / simple_random_selector to pick among multiple sub-features by weight, and set discard_chance_on_air_exposure > 0 on ores to give veins the "cave-eaten" look near air.

Placed features

A placed feature at data/<namespace>/worldgen/placed_feature/ wraps a configured feature with an ordered list of placement modifiers that decide where and how often it appears. Each modifier transforms a stream of candidate positions.

worldgen/placed_feature β€” root schema shape

{
  "feature": "namespace:configured_feature_or_inline",
  "placement": [ /* modifiers applied in order */ ]
}

Every placement modifier

ModifierFieldsEffect
countcount (int provider, 0–256; stack modifiers for more)Duplicate each position N times.
count_on_every_layercount (int provider)N positions per exposed vertical layer.
rarity_filterchance (positive int)Keep position with probability 1/chance.
noise_based_countnoise_to_count_ratio (int), noise_factor (double), noise_offset (double, opt)Count derived from surface noise.
noise_threshold_countnoise_level (double), below_noise (int), above_noise (int)Two-tier count by noise.
in_square(none)Random X/Z offset 0–15 (spreads within the chunk).
height_rangeheight (height provider β€” any form: constant, uniform, biased, trapezoid, weighted_list)Set Y from a height provider.
heightmapheightmap (enum)Set Y one above the named heightmap.
random_offsetxz_spread (int provider, −16..16), y_spread (int provider)Jitter the position.
fixed_placementpositions (list of [x,y,z])Only emit if a listed position is in this chunk.
biome(none)Drop position if the current biome doesn't list this feature.
block_predicate_filterpredicate (block predicate)Keep only where the predicate passes.
surface_relative_threshold_filterheightmap, min_inclusive (int, opt), max_inclusive (int, opt)Keep by height relative to the surface.
surface_water_depth_filtermax_water_depth (int)Keep only where water is shallow enough.
environment_scandirection_of_search (up/down), max_steps (1–32), target_condition (block predicate), allowed_search_condition (block predicate, opt)Walk vertically to a matching block.
carving_mask 1.21–1.21.1 onlystep (air/liquid)Emit positions carved out by carvers.

heightmap enum (used by heightmap and surface_relative_threshold_filter): WORLD_SURFACE_WG, WORLD_SURFACE, OCEAN_FLOOR_WG, OCEAN_FLOOR, MOTION_BLOCKING, MOTION_BLOCKING_NO_LEAVES.

Examples

data/example/worldgen/placed_feature/patch_flowers.json

{
  "feature": "example:flower_patch",
  "placement": [
    { "type": "minecraft:rarity_filter", "chance": 2 },
    { "type": "minecraft:in_square" },
    { "type": "minecraft:heightmap", "heightmap": "MOTION_BLOCKING" },
    { "type": "minecraft:biome" }
  ]
}

data/example/worldgen/placed_feature/ore_iron_upper.json (vanilla-style ore distribution)

{
  "feature": "example:ore_iron",
  "placement": [
    { "type": "minecraft:count", "count": 90 },
    { "type": "minecraft:in_square" },
    { "type": "minecraft:height_range",
      "height": { "type": "trapezoid", "min_inclusive": { "absolute": 80 }, "max_inclusive": { "absolute": 384 } } },
    { "type": "minecraft:biome" }
  ]
}
⚠ Version differences
  • Since 1.18-pre1: placed features introduced (split out of the old configured-feature decorators).
  • Since 1.21-pre2: fixed_placement added.
  • 1.21 / 1.21.1 (pack_format 48): carving_mask is present and valid.
  • Removed 1.21.2 (24w33a, pack_format 57): carving_mask was removed β€” do not use it if targeting pack_format 57 or later.
πŸ“Œ Note

Tentative (26.x snapshots): the count cap is reported to rise to 4096, and random_offset to be renamed offset with discrete x/y/z fields replacing xz_spread/y_spread. Both are unverified and out of scope for a 1.21 pack β€” verify against the live wiki before using.

πŸ’‘ Best practice
  • Canonical ordering: count/rarity → in_square → height/heightmap → filters → biome. Putting biome last prevents wasted work.
  • in_square is almost always required alongside count; without it every duplicated copy lands on the same X/Z.
  • Imitate vanilla ore distributions by pairing count with a trapezoid or uniform height_range.
⚠ Gotcha

/place feature ignores placement modifiers β€” it stamps the configured feature at your cursor. Great for previewing the build, useless for verifying spawn rate.

Feature stacking

"Feature stacking" covers four related ways features layer during generation. Understanding all four is what lets you build composite terrain (a disk with plants on it, ore clusters, cave-wall growth) reliably.

1. The placement pipeline is a stack

A placed feature is an ordered list of placement modifiers, and that list is the stack: a stream of candidate positions flows through it top-to-bottom, and each modifier adds, drops, moves, or duplicates positions. Order matters β€” each modifier sees the stream as the previous one left it (e.g. heightmap before random_offset gives different results than the reverse).

2. Literal stacking β€” the count modifier

count duplicates each position N times (stacking copies onto one candidate). Two consequences:

3. Vertical stacking β€” features that place other features

Several configured-feature types reference other placed features, letting you nest feature logic:

So one biome entry can fan out: a random_selector β†’ several random_patches β†’ each placing a simple_block.

4. Decoration-step layering

A biome's features is a list of 11 lists, one per GenerationStep.Decoration (raw_generation β†’ … β†’ underground_ores β†’ … β†’ top_layer_modification). Two rules fall out:

⚠ Feature-order cycle

Minecraft builds one global feature ordering by topologically sorting every biome's per-step lists. If biome A lists [X, Y] in a step and biome B lists [Y, X] in the same step, that's a cycle β†’ "Feature order cycle found" and the world won't generate. Keep the relative order of shared features identical across all biomes within each step, and reference each placed feature at exactly one step index.

🚧 Limit

Stacking can't target a structure. Placement modifiers only know noise, height, biome, and block predicates β€” never where a jigsaw landed. To hang a feature off a structure, bake a feature_pool_element into the jigsaw instead of stacking a biome feature.

Carvers

A configured carver at data/<namespace>/worldgen/configured_carver/ cuts caves and canyons after base terrain but before most decoration. There is no separate "placed carver" β€” a carver is attached to a biome via the biome's carvers field (e.g. { "air": [ "example:big_caves" ] }). Root:

worldgen/configured_carver β€” root schema shape

{ "type": "minecraft:cave | minecraft:nether_cave | minecraft:canyon", "config": { ... } }

Config fields

Universal fields (all three carver types):

FieldTypeMeaning
probabilityfloat 0–1Chance each chunk attempts this carver.
yheight providerVertical distribution of carve origins.
lava_levelvertical anchorAt/below this Y, carved space fills with lava.
replaceableblock id / tag / listBlocks the carver may cut.
debug_settingsobject (optional)debug_mode (bool) plus air_state, water_state, lava_state, barrier_state block states β€” visualization only.

cave / nether_cave extras: yScale (float provider), horizontal_radius_multiplier (float provider), vertical_radius_multiplier (float provider), floor_level (float provider). nether_cave behaves like cave with wider tunnels and no water carving.

canyon extras: vertical_rotation (float provider) plus a shape object β€” distance_factor, thickness, horizontal_radius_factor (float providers), vertical_radius_default_factor, vertical_radius_center_factor (floats), width_smoothness (int).

data/example/worldgen/configured_carver/big_caves.json

{
  "type": "minecraft:cave",
  "config": {
    "probability": 0.15,
    "y": { "type": "uniform", "min_inclusive": { "above_bottom": 8 }, "max_inclusive": { "absolute": 180 } },
    "yScale": { "type": "uniform", "min_inclusive": 0.1, "max_inclusive": 0.9 },
    "lava_level": { "above_bottom": 8 },
    "replaceable": "#minecraft:overworld_carver_replaceables",
    "horizontal_radius_multiplier": { "type": "uniform", "min_inclusive": 0.7, "max_inclusive": 1.4 },
    "vertical_radius_multiplier": { "type": "uniform", "min_inclusive": 0.8, "max_inclusive": 1.3 },
    "floor_level": { "type": "uniform", "min_inclusive": -1.0, "max_inclusive": -0.4 }
  }
}
⚠ Version differences
  • Since 1.21 (pack_format 48): folder is singular worldgen/configured_carver/.
  • 1.16.2 – 1.21.x: replaceable, lava_level, and debug_settings are all valid.
  • Since 1.18: carvers use a height-provider y and multiplier-based radii.
πŸ“Œ Note

Tentative (26.x snapshots): nether_cave, replaceable, lava_level, and debug_settings are reported removed, yScale renamed, and new cave-shape fields (thickness, start_vertical_radius_multiplier) added. All unverified and out of scope for a 1.21 pack.

🎩 Trick

Attach a carver only through a biome's carvers list; probability is the main density knob. Set debug_mode: true with distinct air_state/water_state/lava_state/barrier_state blocks to make cave shapes visible while tuning.

Sources