Chapter 43 — Features and Placed Features
What You’ll Build
Look closely at any Minecraft world and you’ll see it’s covered in small, scattered details: a clump of
flowers here, a tree there, a blob of iron ore deep underground, an amethyst geode hidden in a cave, a
little lake of water sitting in a hollow. The game calls each of these a feature: a single
generated decoration. In the last chapter you built a biome, and you saw it had a features field that
you mostly left alone. This chapter is about what actually goes in that field.
By the end you’ll understand the two files that work together to put a feature in the world: a
configured feature (the what: which kind of feature, with which settings) and a placed
feature (the where: that configured feature plus a list of rules deciding how many appear, how
high up, and in which biomes). You’ll write a real placed feature, gate it to specific biomes and a
height band, test it instantly with the placefeature command, and wire it into a biome so it
generates naturally. You’ll also build a placement wrapper for a giant-mushroom feature.
There’s one honest catch you’ll meet head-on in this chapter, and it’s worth saying up front: this
chapter teaches the placement machinery in complete detail, but the inner settings of the individual
feature types (the exact knobs on ore, tree, geode, and friends) are deep enough to be their own
topic. So you’ll learn to do everything around a configured feature (and reference the ones
the game already ships) while we point you to the wiki for the one piece you’ll look up for your exact
version. Knowing precisely where the edge of your knowledge is, is itself a skill.
Figure (to be captured). a custom band of ore generating only in a snowy biome, shown via the F3 debug screen with the biome name visible
Two files, one idea: what and where
A feature in Minecraft is split across two ideas, and almost every confusion about world generation comes from mixing them up. Keep them separate and the whole system falls into place.
Feature. A single thing the world generator places: a tree, a blob of ore, a patch of flowers, a geode, a lake. Features are the things that get placed in a world.
Configured feature. The what. A configured feature is the configuration of a feature type: it picks a feature type (the kind of feature) and fills in its settings. It does not say where in the world it goes.
Placed feature. The where. A placed feature determines where a configured feature should be attempted to be placed, using placement modifiers. It wraps a configured feature in a list of rules. Placed features can be referenced in biomes. This is the file a biome actually points at.
So the chain is: a placed feature points at a configured feature, and a biome points at the placed feature. Three links. The configured feature knows how to build one copy of the thing; the placed feature decides how many and where; the biome decides which biome gets it.
Each kind lives in its own folder inside your data pack, right next to the worldgen/biome/ folder you
made in Chapter 42:
data/mypack/worldgen/
biome/ the biomes you built in Chapter 42
configured_feature/ the "what" files (one feature + its settings)
placed_feature/ the "where" files (a configured feature + placement rules)
Both paths are exact: configured features are stored as JSON files within a data pack in the
data/<namespace>/worldgen/configured_feature folder, and placed features are stored the same way in
the worldgen/placed_feature folder.
Feature types are hardcoded — and that matters
Here is a rule that surprises people: you cannot invent a new kind of feature. A feature type determines how and what a configured feature should generate, and feature types are hardcoded: new ones cannot be added through data packs. The game ships a fixed set of feature-type builders (the code that knows how to grow a tree, scatter a flower patch, hollow out a geode), and a data pack’s job is only to configure one of those builders, never to write a brand-new one.
This is different from most of what you’ve done in this book. A recipe or a loot table is content you
write from scratch. A configured feature is more like filling in a form for a machine that already
exists: you choose the machine (the type) and set its dials (the config).
Modern Minecraft. Old tutorials sometimes talk about “custom structures” and “custom features” as if they were the same thing. They aren’t. Features are the small natural decorations covered in this chapter (ores, trees, patches). Structures (villages, temples, mineshafts) are a separate system with their own folder. This chapter is only about features.
The configured feature file (and where to look up the inner config)
The configured feature file has a simple outer shape. The whole root format is just:
- a root object with two fields
type— a string: the ID of the feature typeconfig— a compound (object): the configuration of this configured feature, whose properties depend on the value oftype.
That config’s contents depend on which type you chose. An ore-type feature’s config has dials
about which blocks to replace and how big the blob is; a tree-type feature’s config has dials about
the trunk and leaves; and so on. Here is where this chapter draws its line:
The outer wrapper (type + config) is the same for every feature, and feature types are hardcoded.
The individual feature types and the fields inside their config objects are a deep, type-by-type topic.
The exact fields for the ore, tree, random_patch, geode, or lake configs each differ. So
where you need a real configured feature in this chapter, we’ll reference one the game already ships
(a vanilla configured feature), and when you want to author a new one from scratch, open that feature
type’s page on the live wiki (or copy a vanilla example) and write the fields you find there for your
exact version.
This isn’t as limiting as it sounds, because vanilla already ships hundreds of configured features
(every ore blob, every tree, every flower patch you see in a normal world is one), and your placed
feature can point straight at them by their ID. You’ll do exactly that in the walkthrough. Some feature
types are even “configuration-less features”: they have a file in the configured_feature folder but
no settings at all.
Under the Hood (skippable). The reason the
configshape changes withtypeis that each feature type is a separate piece of Java code with its own settings object. The data pack just hands that code a blob of JSON shaped the way that particular type expects. It’s the same “the fields depend on the type” pattern you’ve seen in predicates and in placement modifiers below. Minecraft uses it all over world generation.
The placed feature file
The placed feature is where this chapter does its real work, and happily it’s documented in full. Its root format:
- a root object with two fields
feature— the feature to place. This is a reference to a configured feature: either its ID (a string likeminecraft:ore_iron) or an entire configured feature written inline as an object.placement— a list of placement modifiers, applied in order. Each entry is an object with atypestring, and its other fields depend on the value oftype.
So a placed feature is a configured feature plus an ordered list of small rules. Those rules are called placement modifiers.
What the placement list actually does
This is the most important paragraph in the chapter, so read it slowly. When a placed feature is reached through a biome, it starts by trying to place its configured feature once, at the northwest corner of each chunk, at the bottom of the world. That’s the starting point: one attempt, one position, at the very bottom of a 16×16 chunk column. The placement modifiers then run in order, and each one can do one of three things to the position(s):
- Move a position (e.g. raise it to a sensible height).
- Multiply positions (e.g. turn one attempt into twelve).
- Filter positions out (e.g. drop any that aren’t in the right biome).
Put plainly: placement modifiers can change the position of the feature and the amount of placements, applied in order to determine where feature placement attempts should occur, and each placement attempt applies the placement modifiers separately. So a typical list reads like a little recipe: make several attempts → spread them around the chunk → pick a height → keep only the ones in the right biome. You build the behavior you want by stacking these small rules.
Modern Minecraft. If you followed a very old tutorial, you may have seen worldgen “decorators” with a single configured shape. The current system splits that into the configured feature and this ordered list of placement modifiers. If a tutorial talks about a
decoratedfeature type or adecoratorfield, it is out of date.
There are two other ways a placed feature can be reached, which is useful to know: when it’s referenced
from inside another configured feature, or through the placefeature command, it starts at the
feature’s (or player’s) own position instead of the chunk corner. You’ll use the command path to test
things in a moment.
The placement-modifier catalogue
Every placement-modifier type below comes with its real fields. There are a lot of them; you don’t
need all of them at once. We’ll group them by the three jobs from above so you can find the right tool
quickly.
Modifiers that multiply (make more attempts)
count— “Returns multiple copies of the current block position.” Field:count, a number between 0 and 4096. (It can also be a small object for a random count, see the note below.) Stacking severalcountmodifiers multiplies, so you can exceed 4096.count_on_every_layer— likecount, but it places on each horizontal layer separated by air, lava, or water in the chunk. Field:count(0–256). Good for cave decorations on every ledge.noise_based_countandnoise_threshold_count— make the count depend on a noise value, so density varies smoothly across the world. These have several numeric fields (noise_factor,noise_offset,noise_to_count_ratio, ornoise_level/below_noise/above_noise). You’ll rarely reach for them as a beginner.
A note on the
countvalue.count’s value can be an int or a compound. A plain number means “exactly this many.” The object form lets it be a random range. Minecraft calls that an int provider. We’ll only use the plain-number form in this chapter. If you ever need a random count, look up the int-provider format on the wiki for your version and use the object form there.
Modifiers that move (change the position)
in_square— for both X and Z, it adds a random value between 0 and 15. No fields. This is the workhorse: it spreads your attempts randomly across the 16×16 chunk instead of all landing on the corner. Almost every placed feature uses it.height_range— sets the Y coordinate to a value provided by a height provider. Field:height, a height provider (covered just below). This is how you say “somewhere between Y=20 and Y=60.”heightmap— sets the Y coordinate to one block above the heightmap. Field:heightmap, one ofMOTION_BLOCKING,MOTION_BLOCKING_NO_LEAVES,OCEAN_FLOOR,OCEAN_FLOOR_WG,WORLD_SURFACE, orWORLD_SURFACE_WG. Use this for surface features (trees, flowers): it drops the feature onto the ground instead of leaving it at a fixed height. Roughly,WORLD_SURFACEis the top block including trees and leaves, andOCEAN_FLOORis the top solid block ignoring water. But check the precise definitions of each heightmap name on the wiki for your version.random_offset— nudges the position by an amount. Fields:xz_spreadandy_spread(each −16 to 16). Despite the name, the offset is only random if you give it a random provider; a fixed number always shifts by that exact amount.fixed_placement— places at exact listed positions. Field:positions, a list of[x, y, z]triples. Used when you want a feature at known coordinates.
Height providers and vertical anchors
height_range’s height field is a small object called a height provider. The type is one of:
constant, uniform (random, even spread), biased_to_bottom and
very_biased_to_bottom (random, leaning low, great for ores), trapezoid (random, leaning toward the
middle), and weighted_list. The common ones, uniform and the biased pair, take a min_inclusive and
a max_inclusive, each a vertical anchor.
Vertical anchor. How a Y value is written. There are three forms:
absolute(a flat Y like the F3 screen shows),above_bottom(counting up from the world floor), andbelow_top(counting down from the world ceiling). So{ "absolute": 40 }means Y=40, and{ "above_bottom": 8 }means 8 blocks above the bottom of the world.
A uniform height between Y=16 and Y=64 therefore looks like this:
{
"type": "minecraft:uniform",
"min_inclusive": { "absolute": 16 },
"max_inclusive": { "absolute": 64 }
}
Modifiers that filter (drop positions)
biome— returns the current position if the biome at that position includes this placed feature, otherwise returns empty. No fields. This is the one that keeps a feature inside the biomes that asked for it, so it doesn’t bleed across biome borders. Read the warning box below; this one has a sharp edge.rarity_filter— keeps a position with probability1 / chance. Field:chance, a positive integer."chance": 32means “on average, one in 32 attempts survives.” It’s your main tuning knob for “how rare is this thing.”block_predicate_filter— keeps the position only if a block predicate passes. Field:predicate(covered below). Use it for “only place on stone” or “only place where there’s air above.”surface_water_depth_filter— keeps the position only if the water above the surface is shallower thanmax_water_depth. Good for keeping land features out of deep ocean.surface_relative_threshold_filter— keeps the position only if it’s within a height range relative to the surface (heightmap,min_inclusive,max_inclusive). For “just under the surface” effects.environment_scanandcarving_mask— advanced.environment_scanwalks up or down until a block predicate matches (fieldsdirection_of_search,max_steps,target_condition, optionalallowed_search_condition);carving_maskreturns positions carved out by a carver (fieldstep,airorliquid). You’ll meet carvers in Chapter 45.
What Went Wrong? The
biomemodifier can crash your world. Here’s a real warning worth heeding: thebiomemodifier cannot be used in placed features that are referenced from other configured features. If you do it anyway, Minecraft does not catch this type of error automatically on trying to load the world; instead the game runs normally until it tries to generate the feature, which causes the game to crash. Sobiomeis safe in a placed feature that a biome points at (the normal case), but never put it in a placed feature that’s nested inside a configured feature. Symptom: a crash the first time that chunk tries to generate, not at load.
Block predicates (for block_predicate_filter)
A block predicate is a test for the state of a block at a given position in the world. Like
everything in worldgen, it’s a type plus type-specific fields. The useful ones:
Block predicate. A small test object. These are the
types you’ll reach for (among others):true(always matches),all_of/any_of(combine childpredicates),not(invert apredicate),matching_blocks(the block is one of a given list/tag, fieldblocks),matching_block_tag(the block is in a given block tag, fieldtag),solid(the block is solid),replaceable(the block can be replaced, e.g. air/grass), andwould_survive(a given blockstatecould legally be placed here). Each also takes an optionaloffset([X,Y,Z], each −16 to 16) so it can test a neighbouring block, e.g. “is the block below solid?”.
So “only place where the block below is solid ground” is a block_predicate_filter whose predicate is
a solid test with offset [0, -1, 0].
Getting the feature into the world: decoration steps
You now have a placed feature. How does it actually generate? Through a biome’s features field, the
same field you saw in Chapter 42 and left alone. Now you can fill it in.
The features field is a list of generation steps, usually 11 of them. It’s therefore a
list of lists: an outer list with one slot per decoration step, and each slot holds the placed
features that run during that step. The steps run in a fixed order, and each has a job. Here they are in
order:
features: (a list of 11 steps, in this order)
[0] RAW_GENERATION small end-island features
[1] LAKES lava lakes
[2] LOCAL_MODIFICATIONS amethyst geodes, icebergs
[3] UNDERGROUND_STRUCTURES dungeons, fossils
[4] SURFACE_STRUCTURES desert wells, blue-ice patches
[5] STRONGHOLDS (not used for features in vanilla)
[6] UNDERGROUND_ORES ore blobs, dirt/gravel disks
[7] UNDERGROUND_DECORATION infested blocks, nether ore/gravel blobs
[8] FLUID_SPRINGS water and lava springs
[9] VEGETAL_DECORATION trees, bamboo, cacti, kelp, vegetation
[10] TOP_LAYER_MODIFICATION surface freezing (snow/ice)
This list answers the chapter’s questions about which feature goes where: a geode belongs in step
LOCAL_MODIFICATIONS, an ore in UNDERGROUND_ORES, a tree in VEGETAL_DECORATION, a lava lake in
LAKES. The position in the outer list is the step, so an ore feature goes in the 7th slot
(UNDERGROUND_ORES).
What Went Wrong? The cross-biome ordering rule. There’s a subtle constraint here: within one step, the same placed features in the same step in two biomes cannot be in different orders. If two biomes both place
ore_dirtandore_gravelinUNDERGROUND_ORES, they must list them in the same relative order. Mismatched orders make the world fail to load. The safe habit: keep a consistent order for any features you reuse across biomes.
Under the Hood (skippable). Why a fixed order? Because features can build on each other: trees should generate after the ground is shaped, snow should fall after the trees exist. Fixing the step order makes that predictable across every biome in the world at once. These step names are also used by structure generation.
Walkthrough — Practice 1: a custom ore band in chosen biomes
Let’s build a placed feature that scatters a configured ore feature underground, but only in chosen
biomes and only between Y=8 and Y=40. Rather than author the ore-type config from scratch here,
we’ll point feature at a configured feature the game already ships and focus on the placement, which
is the part we can author with confidence.
Create this file:
data/mypack/worldgen/placed_feature/frozen_ore.json
{
"feature": "minecraft:ore_diamond",
"placement": [
{
"type": "minecraft:count",
"count": 8
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:height_range",
"height": {
"type": "minecraft:uniform",
"min_inclusive": { "absolute": 8 },
"max_inclusive": { "absolute": 40 }
}
},
{
"type": "minecraft:biome"
}
]
}
Read the placement list top to bottom and you can narrate exactly what happens: start with one attempt
at the chunk corner → count 8 makes eight attempts → in_square scatters them randomly across
the chunk → height_range drops each to a random Y between 8 and 40 (a uniform height provider
using absolute vertical anchors) → biome keeps only the attempts whose biome actually lists this
feature. Eight diamond-ore attempts per chunk, underground, but only where we allow it.
About the referenced ID.
minecraft:ore_diamondis the configured feature we’re pointing at as a stand-in for “an ore blob.” Confirm the exact ID for your version on the official wiki. And once you know theore-type config fields, you can replace this reference with your own configured feature inworldgen/configured_feature/for a truly custom ore. The placement file above stays exactly the same either way.
Test it instantly with placefeature
Worldgen files live in dynamic registries, which (as you learned back in Chapter 9) do not
reload with /reload. Changing a biome or feature normally means making a brand-new world (or restarting)
to see it. That’s a slow feedback loop. There’s a shortcut for testing a feature on the spot: the
placefeature command.
Put this in a function so you follow the book’s rule of writing commands in .mcfunction files, not the
chat bar:
data/mypack/function/test_ore.mcfunction
placefeature minecraft:ore_diamond ~ ~-5 ~
The command is placefeature <feature> [<pos>]: it places the named configured feature at a
position (here, 5 blocks below you). Two things to notice. First, placefeature takes a configured
feature, not a placed feature; it tests “does this feature build correctly here?”, skipping the
placement rules. Second, it has a few failure cases: it fails if there’s no configured feature with the
provided ID, if the requirements for the selected feature are not met, or if the position isn’t loaded.
So if nothing appears, check the ID first.
This lets you confirm the feature works right where you stand, then trust your placement list to handle the scattering once you reboot the world.
Wire it into a biome
Finally, reference the placed feature from a biome so it generates naturally. In a biome file from
Chapter 42, the features field is the list of 11 steps; an ore goes in the UNDERGROUND_ORES step,
which is the 7th slot (index 6). Here’s the features field with our placed feature dropped into that
step (empty steps shown as empty lists so the ordering stays correct):
"features": [
[],
[],
[],
[],
[],
[],
[ "mypack:frozen_ore" ],
[],
[],
[],
[]
]
Each inner list is one decoration step; our mypack:frozen_ore placed feature sits in the
UNDERGROUND_ORES step. Because the placed feature ends with the biome modifier, the ore now appears
in this biome and stops at its borders. Save, make a new world (dynamic registries need a reboot,
not /reload), and explore the biome’s caves.
Figure (to be captured). diamond ore generating in a band underground inside the custom biome, none visible in the neighbouring biome
Practice 2: a giant mushroom feature
Your second task is to scatter a giant-mushroom feature across a biome’s surface. The same split applies: the giant-mushroom shape is a configured feature (a feature type the game already knows how to build), and we author the placement. As before we reference an existing configured feature and put all our effort into the placement list, this time with a surface heightmap and a block-predicate filter so mushrooms only sprout on suitable ground.
data/mypack/worldgen/placed_feature/giant_mushroom.json
{
"feature": "minecraft:huge_red_mushroom",
"placement": [
{
"type": "minecraft:rarity_filter",
"chance": 12
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:heightmap",
"heightmap": "WORLD_SURFACE_WG"
},
{
"type": "minecraft:block_predicate_filter",
"predicate": {
"type": "minecraft:matching_blocks",
"offset": [0, -1, 0],
"blocks": "minecraft:mycelium"
}
},
{
"type": "minecraft:biome"
}
]
}
Narrate it: rarity_filter 12 means most chunks get nothing and roughly one chunk in twelve gets a
single attempt (mushrooms should be rare) → in_square scatters that attempt across the chunk →
heightmap WORLD_SURFACE_WG lifts it to the ground surface instead of the world bottom →
block_predicate_filter with a matching_blocks predicate checking the block below (offset
[0,-1,0]) keeps only positions standing on minecraft:mycelium → biome keeps it inside the
intended biome. A rare giant mushroom, only on mycelium, only in your biome.
Then add mypack:giant_mushroom to the VEGETAL_DECORATION step (the 10th slot, index 9) of a biome’s
features list, since that’s the step for trees, bamboo, cacti, kelp, and other ground and ocean
vegetation. Reboot into a new world to see it.
About the referenced ID and new mushroom shapes.
minecraft:huge_red_mushroomstands in for “a giant-mushroom configured feature”; confirm the real ID for your version. Authoring a new mushroom or tree shape means writing atree-type config (trunk provider, foliage provider, size, and so on). Open that feature type’s page on the wiki for those fields. The placement file is fully yours regardless.
Try It! Change
huge_red_mushroomto a different surface configured feature, swap the predicate’sblockstominecraft:grass_block, and bumpchancedown to4to make the feature common. You’re reusing the exact same placement skeleton. That’s the point of the what/where split.
What Can Go Wrong
- Edited a feature or biome and
/reloaddid nothing. Worldgen lives in dynamic registries, which don’t hot-reload. You must create a new world (or restart the game and re-enter) to pick up changes. Already-generated chunks keep their old generation regardless. Useplacefeatureto spot- check a configured feature without a reboot, but the placement and biome wiring only take effect in freshly generated chunks. - The world crashes when you reach the biome. Most often the
biomeplacement modifier is sitting inside a placed feature that’s referenced from another configured feature. This isn’t caught at load, and crashes at generation time. Keepbiomeonly in placed features that a biome points at directly. - The world won’t load at all after adding a feature to two biomes. Check the cross-biome ordering rule: any features shared between biomes in the same step must appear in the same relative order in every biome. Reorder them to match.
- Nothing generates, no crash. Likely your
featureID is wrong (“no configured feature with the provided ID” is aplacefeaturefailure case), or you put the placed feature in the wrong decoration step, or you forgot thebiomemodifier so the biome never claims it. Test the configured feature withplacefeaturefirst to isolate which half is broken.
What You Know Now
You can now describe the two-file split at the heart of Minecraft world decoration: the configured
feature (the what, a hardcoded feature type plus a config) and the placed feature (the
where, a configured feature wrapped in an ordered placement list). You can read and write a
placement list, choosing placement modifiers that multiply attempts (count), spread and position
them (in_square, height_range with a height provider and vertical anchors, heightmap), and filter
them (rarity_filter, biome, block_predicate_filter with a block predicate). You know how a placed
feature reaches the world through a biome’s features field and its eleven named decoration steps,
and you can test a configured feature on the spot with placefeature instead of waiting for a reboot.
You can now build: a custom ore band gated to chosen biomes and heights, and a rare surface feature like
a giant mushroom that only grows on the ground you choose, both by authoring the placement around an
existing configured feature. The one piece you’ll look up rather than memorize is the inner config of
each feature type; you know exactly where that edge is and how to find it on the wiki for your version.
Next, in
Chapter 44, you’ll stop decorating existing worlds and start building whole new ones: custom
dimensions.