1. Wiki
  2. /World Generation
  3. /Features and feature rules

Features and feature rules

Add ores, plants, trees and structures to Minecraft Bedrock world generation with features and feature rules, with a ruby ore example and every feature type.

Everything that decorates the land is a feature: ore veins, trees, flowers, grass, boulders, springs, coral. If it is not the basic terrain and not a mob, it is probably a feature.

To get a feature into the world you need two files:

  • A feature says what to place: a vein of ore, a tree, a single block.
  • A feature rule says where and how often: which biomes, how many times per chunk, at what height.

In this guide you will make ruby ore appear underground in every overworld biome.

The files

Behavior pack
BP/
  blocks/
    ruby_ore.json
  features/
    ruby_ore_feature.json
  feature_rules/
    ruby_ore_rule.json

Step 1: the ore block

You need a block to place first. Make a normal custom block called wiki:ruby_ore with a texture and a loot table. If you have not made a block yet, follow Your first custom block.

Step 2: the feature

BP/features/ruby_ore_feature.json
{
  "format_version": "1.13.0",
  "minecraft:ore_feature": {
    "description": {
      "identifier": "wiki:ruby_ore_feature"
    },
    "count": 6,
    "replace_rules": [
      {
        "places_block": "wiki:ruby_ore",
        "may_replace": [
          "minecraft:stone",
          "minecraft:granite",
          "minecraft:diorite",
          "minecraft:andesite"
        ]
      }
    ]
  }
}
  • The root key, here minecraft:ore_feature, is the feature type. Each file has exactly one. The table at the bottom of this page lists them all.
  • count is how many blocks one vein tries to place. Diamonds use small veins, coal uses big ones.
  • replace_rules says which block goes where. The ore only replaces blocks listed in may_replace, so it never floats in caves or eats through dirt.

A deepslate version

Add a second entry to replace_rules with "places_block": "wiki:deepslate_ruby_ore" and "may_replace": ["minecraft:deepslate"]. One vein then uses the right look in both layers, just like vanilla ores.

Naming rules

  • One feature per file.
  • The file name must match the name part of the identifier. wiki:ruby_ore_feature goes in ruby_ore_feature.json. The namespace is not part of the match.
  • If two packs use the exact same identifier, the pack higher in the list wins. That is how you can replace a vanilla feature.

Step 3: the feature rule

A feature does nothing until a feature rule attaches it to biomes:

BP/feature_rules/ruby_ore_rule.json
{
  "format_version": "1.13.0",
  "minecraft:feature_rules": {
    "description": {
      "identifier": "wiki:ruby_ore_rule",
      "places_feature": "wiki:ruby_ore_feature"
    },
    "conditions": {
      "placement_pass": "underground_pass",
      "minecraft:biome_filter": [
        {
          "test": "has_biome_tag",
          "operator": "==",
          "value": "overworld"
        }
      ]
    },
    "distribution": {
      "iterations": 4,
      "coordinate_eval_order": "zyx",
      "x": {
        "distribution": "uniform",
        "extent": [0, 16]
      },
      "y": {
        "distribution": "triangle",
        "extent": [-48, 16]
      },
      "z": {
        "distribution": "uniform",
        "extent": [0, 16]
      }
    }
  }
}

The rule has three parts.

description

  • identifier names the rule. Like features, the name part must match the file name.
  • places_feature is the feature this rule places. One rule controls one feature.

conditions

minecraft:biome_filter picks the biomes. It is a list of filter tests, and the one you will use almost every time is has_biome_tag. Every biome checks the filter: the ones that pass get the feature.

You can combine tests with all_of and any_of. This one picks warm overworld biomes that are not oceans:

Inside conditions
"minecraft:biome_filter": [
  { "test": "has_biome_tag", "operator": "==", "value": "overworld" },
  {
    "any_of": [
      { "test": "has_biome_tag", "operator": "==", "value": "desert" },
      { "test": "has_biome_tag", "operator": "==", "value": "mesa" }
    ]
  },
  { "test": "has_biome_tag", "operator": "!=", "value": "ocean" }
]

To put ruby ore only in the Ruby Grove, test for its own tag: "value": "ruby_grove".

placement_pass says when the feature is placed compared to others. Passes run in this order:

PassGood for
first_passThings everything else should build on.
before_underground_pass, underground_pass, after_underground_passOres, blobs of dirt or gravel, cave decorations.
before_surface_pass, surface_pass, after_surface_passTrees, flowers, grass, boulders.
before_sky_pass, sky_pass, after_sky_passThings up in the air.
final_passLast touches, after everything else.
pregeneration_passCave carvers only.

Features in the same pass have no fixed order between them.

distribution

This decides how many copies try to generate in each chunk and where.

FieldWhat it does
iterationsHow many times to try per chunk. Here, 4 veins.
x, y, zWhere each try lands. A fixed number, a range, or a Molang expression.
scatter_chanceOptional chance for the whole chunk, like { "numerator": 1, "denominator": 4 } for 1 in 4 chunks. If it fails, no tries run at all.
coordinate_eval_orderThe order the coordinates are worked out in, like "xzy" (the default) or "zyx". Matters when one coordinate uses another.

For a feature rule, x and z count from the corner of the chunk, so [0, 16] covers the whole chunk. y is the world height.

Each range has a distribution type that shapes where values land:

TypeResult
uniformEvery value equally likely.
triangleMost values near the middle of the range, fewer at the ends. Great for ores.
gaussianBunched around the middle, like a bell.
inverse_gaussianBunched at both ends, few in the middle.
fixed_gridEvenly spaced steps, set with step_size and grid_offset.
jittered_gridA grid with each point nudged a little at random.

For things on the ground, like plants, set y with Molang so it lands on the surface:

Inside distribution
"y": "query.heightmap(variable.worldx, variable.worldz)"

Ore only in new chunks

Features generate once, when a chunk is first made. Explore far away or make a new world to see your ore. Already-explored land never gets it.

Testing

  1. Turn the pack on in a new world.
  2. Go into spectator mode with /gamemode spectator and fly underground near Y 0.
  3. Look for the ruby texture in the stone. Too rare? Raise iterations or count.

If nothing appears, open the Content Log. The usual causes are a file name that does not match the identifier, a wrong places_feature name, or a block name typo in places_block.

Every feature type

Each feature file uses exactly one of these as its root key. Some place blocks, others only choose between, move or repeat other features. Most vanilla decorations chain several together: for example a scatter feature that runs a search feature that runs a tree.

TypeWhat it does
minecraft:aggregate_featurePlaces a list of features at the same spot, in no fixed order.
minecraft:beards_and_shaversBuilds up or cuts away terrain to make a flat, clear spot for another feature, usually a structure.
minecraft:cave_carver_featureDigs overworld caves through this chunk and its neighbors. Needs pregeneration_pass.
minecraft:conditional_listChecks a list of features in order and places the first one whose condition passes.
minecraft:fossil_featureBuilds a buried skeleton out of bone blocks plus an ore block you choose.
minecraft:geode_featureMakes a round geode with layered shells and an inner filling you can swap out.
minecraft:growing_plant_featureGrows a plant column up from the floor or down from the ceiling, with a body and a tip, like cave vines.
minecraft:height_difference_filter_featureOnly lets another feature place if the ground around the spot passes height checks.
minecraft:horizontal_tree_decoration_featureSticks a block onto the side of something facing a random direction, like shelf mushrooms on a log.
minecraft:multi_block_featurePlaces a block that is made of several parts, optionally turned in a random direction.
minecraft:multiface_featurePlaces thin blocks that cling to floors, walls or ceilings, like glow lichen.
minecraft:multipart_block_column_featureStacks a column of up to four kinds of block (base, middle, narrowing part and tip), in any direction.
minecraft:nether_cave_carver_featureDigs caves in the Nether. Needs pregeneration_pass.
minecraft:ore_featurePlaces a vein of blocks that only replaces the blocks you allow. Used for every ore.
minecraft:partially_exposed_blob_featurePlaces a lump of a block mostly buried in the ground, with only one side showing.
minecraft:rect_layoutFills a chunk's surface with a grid of areas, each holding one feature, with some space left empty.
minecraft:scan_surfaceWalks over every column of a chunk's surface and tries a feature on each.
minecraft:scatter_featurePlaces another feature many times around a spot, with the same x, y, z ranges as a feature rule.
minecraft:sculk_patch_featureSpreads a patch of sculk. Not documented by the game yet.
minecraft:search_featureSearches a box of space, layer by layer, for a spot where another feature fits.
minecraft:sequence_featurePlaces features one after another, each starting where the last one ended.
minecraft:single_block_featurePlaces one block, or one picked at random from a weighted list, with rules for what it can sit on.
minecraft:snap_to_surface_featureMoves the spot onto the nearest floor, ceiling or wall before placing another feature.
minecraft:structure_template_featurePlaces a saved .mcstructure from the structures folder of a behavior pack.
minecraft:surface_relative_threshold_featureOnly places another feature if the spot is far enough below the surface.
minecraft:tree_featureBuilds a tree from a trunk, a canopy and optional roots, with lots of shape options.
minecraft:underwater_cave_carver_featureDigs caves below sea level. Needs pregeneration_pass.
minecraft:vegetation_patch_featureCovers an area of ground with a block, then grows plants on it, like moss patches.
minecraft:weighted_random_featurePicks one feature from a list at random. Bigger weights get picked more often.

Next steps

We use cookies to improve your experience and analyse site traffic. Learn more