FEATURES DOCUMENTATION
Version: 1.15.0.51

This is documentation for a beta release of Minecraft. New features, components, and capabilities in this release are not final and might change without notice before the final release.
Be sure to check the documentation once the release is out of beta if your add-on isn't working properly. Resource and Behavior Packs created for the beta are not guaranteed to work on the final release.

Index

Overview
JSON format
Adding features
Supported features
minecraft:aggregate_feature
minecraft:sequence_feature
minecraft:ore_feature
minecraft:scatter_feature
minecraft:search_feature
minecraft:single_block_feature
minecraft:structure_template_feature
minecraft:tree_feature
minecraft:weighted_random_feature
Attaching features
Feature rules
Feature rule schema
Forced features
Back to top

Overview

Features are decorations scattered throughout the world. Things such as trees, plants, flowers, springs, ore, and coral are all features. Basically, if it isn't the terrain or a mob, it's probably a feature!
Features can be standalone or composed of multiple sub-features. In practice, most features in Minecraft are defined as a chain of two or more features. These chains typically end with features that place blocks in the world. Other feature types control flow such as conditional, sequential, or random distribution.
Back to top

JSON format

All features must specify the version that they target via the "format_version" field. The remainder of the data is contained in independet JSON sub-objects for each supported feature type. These feature types define the behavior of the feature and include properties specific to that behavior. To be valid, a definition must include exactly one of these type objects. See the full feature schema below for additional details and the full list of supported feature types.

Here is a sample feature
{
  "format_version": "1.13.0",
  "minecraft:ore_feature": {
    "description": {
      "identifier": "minecraft:coal_ore_feature"
    },
    "count": 17,
    "places_block": "minecraft:coal_ore",
    "may_replace": [
      {
        "name": "minecraft:stone",
        "states": {
          "stone_type": "andesite"
        }
      },
      {
        "name": "minecraft:stone",
        "states": {
          "stone_type": "andesite_smooth"
        }
      },
      {
        "name": "minecraft:stone",
        "states": {
          "stone_type": "diorite"
        }
      },
      {
        "name": "minecraft:stone",
        "states": {
          "stone_type": "diorite_smooth"
        }
      },
      {
        "name": "minecraft:stone",
        "states": {
          "stone_type": "granite"
        }
      },
      {
        "name": "minecraft:stone",
        "states": {
          "stone_type": "granite_smooth"
        }
      },
      {
        "name": "minecraft:stone",
        "states": {
          "stone_type": "stone"
        }
      }
    ]
  }
}

Back to top

Adding features

Features are read from JSON files in the "features" subfolder of behavior packs. Loading enforces one feature per file; the file name and the name of the feature must match. Feature names can include a namespace of the form "namespace:feature_name" to help distinguish them from features that may be in other behavior packs. This namespace is not considered when matching the filename to the feature name. For example, in a file called "my_tree_feature.json" both "my_tree_feature" and "my_pack_name:my_tree_feature" would be valid identifiers. If two behavior packs define the same feature name (including namespace), then the feature from the highest pack in the stack will be used. This allows users to override base features if desired.
Back to top

Supported features

minecraft:aggregate_feature

'minecraft:aggregate_feature' places a collection of features in an arbitary order. All features in the collection use the same input position. Features should not depend on each other, as there is no guarantee on the order the features will be placed.
Succeeds if: At lease one feature is placed successfully.
Fails if: All features fail to be placed.

Example use: scattering multiple different plants around a monument.
{
  "format_version": 1.3.0,
  "minecraft:aggregate_feature": {
    "description": {
      "identifier": "example:monument_with_flowers_feature"
    },
    "features": [
      "monument_feature",
      "scatter_white_flowers_feature",
      "scatter_yellow_flower_feature"
    ]
  }
}

Back to top

minecraft:sequence_feature

'minecraft:sequence_feature' places a collection of features sequentially, in the order they appear in data. The output position of the previous feature is used as the input position for the next. For example, a tree feature is placed at (0, 0, 0) and places blocks up to (0, 10, 0). The next feature in the sequence begins at (0, 10, 0).
Succeeds if: All features in the sequence are successfully placed.
Fails if: Any feature in the sequence fails to be placed. Features that have not yet been placed at the time of failure are skipped.

Example use: Scattering fruit throughout the canopy of a tree.
{
  "format_version": 1.3.0,
  "minecraft:sequence_feature": {
    "description": {
      "identifier": "example:oak_tree_then_apples_feature"
    },
    "features": [
      "oak_tree_feature",
      "scatter_apples_feature"
    ]
  }
}

Back to top

minecraft:ore_feature

'minecraft:ore_feature' places a vein of blocks to simulate ore deposits. Despite the name, any block can be placed by this feature. During placement, existing world blocks are checked to see if they can be replaced by the new ore block based on the list provided in the 'may_replace' field. If no 'may_replace' field is specified, the ore block can replace any existing block.
Succeeds if: At least one ore block is successfully placed.
Fails if: All ore block placements fail.

Example use: Oil deposits in the sand.
{
  "format_version": 1.13.0,
  "minecraft:ore_feature": {
    "description": {
      "identifier": "example:oil_deposit_feature"
    },
    "places_block": "example:oil_block",
    "count": 12,
    "may_replace": [
      "minecraft:sand"
    ]
  }
}

Back to top

minecraft:scatter_feature

'minecraft:scatter_feature' scatters a feature throughout a chunk. The 'x', 'y', and 'z' fields are per-coordinate parameters. Note that coordinates represent an offset from the input position, not an absolute position. Coordinates may be a single value, a random distribution, or molang expression that resolves to a numeric value. The 'coordinate_eval_order' field is provided for finer control of coordinate resolution (particularly when using the 'grid' distribution). 'iterations' controls how many individual placements should occur if the 'scatter_chance' check succeeds. The 'scatter_chance' check happens once, so either all placements will run or none will.
Succeeds if: At least one feature placement succeeds.
Fails if: All feature placements fail.

Example use: Scattering flowers at sea level across half the chunks in a biome.
{
  "format_version": 1.13.0,
  "minecraft:scatter_feature": {
    "description": {
      "identifier": "example:scatter_flowers_feature"
    },
    "places_feature": "example:flower_feature",
    "iterations": 10,
    "scatter_chance": 50.0,
    "x": {
      "distribution": "uniform",
      "extent": [ 0, 15 ]
    },
    "y": 64,
    "z": {
      "distribution": "uniform",
      "extent": [ 0, 15 ]
    }
  }
}

Back to top

minecraft:search_feature

'minecraft:search_feature' sweeps a volume searching for a valid placement location for its referenced feature. The 'search_volume' field specifies the axis-aligned bounding box that defines the boundaries of the search. The search sweeps along the axis defined by the 'search_axis' field, layer by layer. For example, if 'search_axis' = '-x', blocks with greater x values will be checked before blocks with lower x values. Each layer is searched from the bottom-left to the top-right before moving to the next layer along the axis. By default, only one valid position must be found, but this can be altered by specifying the 'required_successes' field. If fewer than the required successes are found, no placement will occur.
Succeeds if: The number of valid positions is equal to the value specified by 'required_successes'.
Fails if: The number of valid positions is less than the value specified by 'required_successes'.

Example use: Attaching apples to a tree canopy
{
  "format_version": 1.13.0,
  "minecraft:search_feature": {
    "description": {
      "identifier": "example:find_valid_apples_feature"
    },
    "places_feature": "example:apple_feature",
    "search_volume": {
      "min": [ -3, -3, -3 ],
      "max": [ 3, 3, 3 ]
    },
    "search_axis": "-y",
    "required_successes": 3
}

Back to top

minecraft:single_block_feature

'minecraft:single_block_feature' places a single block in the world. The 'may_place_on' and 'may_replace' fields are whitelists which specify where the block can be placed. If these fields are omitted, the block can be placed anywhere. The block's internal survivability and placement rules can optionally be enforced with the 'enforce_survivability_rules' and 'enforce_placement_rules' fields. These rules are specified per-block and are typically designed to produce high quality gameplay or natural behavior. However, enabling this enforcement may make it harder to debug placement failures.
Succeeds if: The block is successfully placed in the world.
Fails if: The block fails to be placed.

Example use: Placing a single pumpkin block.
{
  "format_version": 1.13.0,
  "minecraft:single_block_feature": {
    "description": {
      "identifier": "example:single_pumpkin_feature"
    },
    "places_block": "example:pumpkin",
    "enforce_placement_rules": true,
    "enforce_survivability_rules": true,
    "may_place_on": [
      "example:grass"
    ],
    "may_replace": [
      "example:air"
    ]
  }
}

Back to top

minecraft:structure_template_feature

'minecraft:structure_template_feature' places a structure in the world. The structure must be stored as a .mcstructure file in the "structures" subdirectory of a behavior pack. It is possible to reference structures that are part of other behavior packs, they do not need to come from the same behavior pack as this feature. Constraints can be defined to specify where the structure is allowed to be placed. During placement, the feature will search for a position within the 'adjustment_radius' that satisfies all constraints. If none are found, the structure will not be placed.
Succeeds if: The structure is placed in the world.
Fails if: The structure fails to be placed within the world.

Example use: Place a hot air balloon structure that "floats" in the air.
{
  "format_version": 1.13.0,
  "minecraft:structure_template_feature": {
    "description": {
      "identifier": "example:hot_air_balloon_feature"
    },
    "structure_name": "example:hot_air_balloon",
    "adjustment_radius": 8,
    "facing_direction": "random",
    "constraints": {
      "unburied": {},
      "block_intersection": {
        "block_whitelist": [
          "example:air"
        ]
      }
    }
  }
}

Back to top

minecraft:tree_feature

Feature type 'minecraft:tree_feature' has not yet been documented.
Back to top

minecraft:weighted_random_feature

'minecraft:weighted_random_feature' randomly selects and places a feature based on a weight value. Weights are relative, with higher values making selection more likely.
Succeeds if: The selected feature is placed.
Fails if: The selected feature fails to be placed.

Example use: Selecting and placing a variant of a flower.
{
  "format_version": 1.13.0,
  "minecraft:weighted_random_feature": {
    "description": {
      "identifier": "example:select_flower_feature"
    },
    "features": [
      [ "example:white_flower_feature", 1 ],
      [ "example:red_flower_feature", 2 ],
      [ "example:blue_flower_feature", 1 ],
      [ "example:yellow_flower_feature", 4 ]
    ]
  }
}

Back to top

Feature schema

Here is the complete feature schema
  {
      version "format_version"
      object "minecraft:aggregate_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          array "features"[1,*] // Collection of features to be placed one by one. No guarantee of order. All features use the same input position.
          {
              feature_reference "<any array element>" : opt
          }
          enumerated_value "early_out"<"none", "first_failure", "first_success"> : opt // LIKELY TO BE CHANGED: Do not continue placing features once either the first success or first failure has occurred.
      }
      object "minecraft:sequence_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          array "features"[1,*] // List of features to be placed in sequence. The output position of the previous feature is used as the input position to the next.
          {
              feature_reference "<any array element>" : opt
          }
      }
      object "minecraft:ore_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          block_reference "places_block" // Reference to the block to be placed.
          int "count"<1-*> // The number of blocks to be placed.
          array "may_replace"[1,*] : opt // A list of blocks that may be replaced during placement. Omit this field to allow any block to be replaced.
          {
              block_reference "<any array element>" : opt
          }
      }
      object "minecraft:scatter_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          feature_reference "places_feature" // Named reference of feature to be placed
          bool "project_input_to_floor" : opt // If true, snaps the y-value of the scattered position to the terrain heightmap. If false or unset, y-value is unmodified.
          molang "iterations" // Number of scattered positions to generate
          object "scatter_chance" : opt // Probability numerator / denominator that this scatter will occur.  Not evaluated each iteration; either no iterations will run, or all will.
          {
              int "numerator"<1-*>
              int "denominator"<1-*>
          }
          molang "scatter_chance" : opt // Probability (0-100] that this scatter will occur.  Not evaluated each iteration; either no iterations will run, or all will.
          enumerated_value "coordinate_eval_order"<"xyz", "xzy", "yxz", "yzx", "zxy", "zyx"> : opt // The order in which coordinates will be evaluated. Should be used when a coordinate depends on another. If omitted, defaults to "xzy".
          molang "x" : opt // Expression for the coordinate (evaluated each iteration).  Mutually exclusive with random distribution object below.
          object "x" : opt // Distribution for the coordinate (evaluated each iteration).  Mutually exclusive with Molang expression above.
          {
              enumerated_value "distribution"<"uniform", "gaussian", "inverse_gaussian", "fixed_grid", "jittered_grid"> // Type of distribution - uniform random, gaussian (centered in the range), or grid (either fixed-step or jittered)
              int "step_size"<1-*> : opt // When the distribution type is grid, defines the distance between steps along this axis
              int "grid_offset"<0-*> : opt // When the distribution type is grid, defines the offset along this axis
              array "extent"[2]
              {
                  molang "[0..0]" : opt // Lower bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                  molang "[1..1]" : opt // Upper bound (inclusive) of the scatter range, as an offset from the input point to scatter around
              }
          }
          molang "z" : opt // Expression for the coordinate (evaluated each iteration).  Mutually exclusive with random distribution object below.
          object "z" : opt // Distribution for the coordinate (evaluated each iteration).  Mutually exclusive with Molang expression above.
          {
              enumerated_value "distribution"<"uniform", "gaussian", "inverse_gaussian", "fixed_grid", "jittered_grid"> // Type of distribution - uniform random, gaussian (centered in the range), or grid (either fixed-step or jittered)
              int "step_size"<1-*> : opt // When the distribution type is grid, defines the distance between steps along this axis
              int "grid_offset"<0-*> : opt // When the distribution type is grid, defines the offset along this axis
              array "extent"[2]
              {
                  molang "[0..0]" : opt // Lower bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                  molang "[1..1]" : opt // Upper bound (inclusive) of the scatter range, as an offset from the input point to scatter around
              }
          }
          molang "y" : opt // Expression for the coordinate (evaluated each iteration).  Mutually exclusive with random distribution object below.
          object "y" : opt // Distribution for the coordinate (evaluated each iteration).  Mutually exclusive with Molang expression above.
          {
              enumerated_value "distribution"<"uniform", "gaussian", "inverse_gaussian", "fixed_grid", "jittered_grid"> // Type of distribution - uniform random, gaussian (centered in the range), or grid (either fixed-step or jittered)
              int "step_size"<1-*> : opt // When the distribution type is grid, defines the distance between steps along this axis
              int "grid_offset"<0-*> : opt // When the distribution type is grid, defines the offset along this axis
              array "extent"[2]
              {
                  molang "[0..0]" : opt // Lower bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                  molang "[1..1]" : opt // Upper bound (inclusive) of the scatter range, as an offset from the input point to scatter around
              }
          }
      }
      object "minecraft:search_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          feature_reference "places_feature" // Named reference of feature to be placed
          object "search_volume" // Axis-aligned bounding box that will be searched for valid placement positions. Expressed as offsets from the input position.
          {
              array "min"[3] // Minimum extent of the bounding volume expressed as [ x, y, z ]
              {
                  int "[0..0]" // x_min
                  int "[1..1]" // y_min
                  int "[2..2]" // z_min
              }
              array "max"[3] // Maxium extent of the bounding volume expressed as [ x, y, z ]
              {
                  int "[0..0]" // x_max
                  int "[1..1]" // y_max
                  int "[2..2]" // z_max
              }
          }
          enumerated_value "search_axis"<"-x", "+x", "-y", "+y", "-z", "+z"> // Axis that the search will sweep along through the 'search_volume'
          int "required_successes"<1-*> : opt // Number of valid positions the search must find in order to place the referenced feature
      }
      object "minecraft:single_block_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          block_reference "places_block" // Reference to the block to be placed.
          bool "enforce_placement_rules" // If true, enforce the block's canPlace check.
          bool "enforce_survivability_rules" // If true, enforce the block's canSurvive check.
          object "may_attach_to" : opt
          {
              int "min_sides_must_attach"<1-4> : opt
              bool "auto_rotate" : opt // Automatically rotate the block to attach sensibly.
              block_reference "top" : opt
              array "top" : opt
              {
                  block_reference "<any array element>"
              }
              block_reference "bottom" : opt
              array "bottom" : opt
              {
                  block_reference "<any array element>"
              }
              block_reference "north" : opt
              array "north" : opt
              {
                  block_reference "<any array element>"
              }
              block_reference "east" : opt
              array "east" : opt
              {
                  block_reference "<any array element>"
              }
              block_reference "south" : opt
              array "south" : opt
              {
                  block_reference "<any array element>"
              }
              block_reference "west" : opt
              array "west" : opt
              {
                  block_reference "<any array element>"
              }
              block_reference "all" : opt
              array "all" : opt
              {
                  block_reference "<any array element>"
              }
              block_reference "sides" : opt
              array "sides" : opt
              {
                  block_reference "<any array element>"
              }
          }
          array "may_replace" : opt
          {
              block_reference "<any array element>" : opt // A list of blocks that may be replaced during placement. Omit this field to allow any block to be replaced.
          }
      }
      object "minecraft:structure_template_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          structure_reference "structure_name" // Reference to the structure to be placed.
          int "adjustment_radius"<0-16> : opt // How far the structure is allowed to move when searching for a valid placement position. Search is radial, stopping when the nearest valid position is found. Defaults to 0 if omitted.
          enumerated_value "facing_direction"<"north", "south", "east", "west", "random"> : opt // Direction the structure will face when placed in the world. Defaults to "random" if omitted.
          object "constraints" // Specific constraints that must be satisfied when placing this structure.
          {
              object "grounded" : opt // When specified, ensures the structure is on the ground.
              object "unburied" : opt // When specified, ensures the structure has air above it.
              object "block_intersection" : opt // When specified, ensures the structure only intersects with whitelisted blocks.
              {
                  array "block_whitelist" // List of blocks the owning structure is allowed to intersect with.
                  {
                      block_reference "<any array element>" : opt
                  }
              }
          }
      }
      object "minecraft:tree_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          object "can_be_submerged" : opt
          {
              int "max_depth"<1-*>
          }
          bool "can_be_submerged" : opt
          block_reference "base_block" : opt
          array "base_block" : opt
          {
              block_reference "<any array element>"
          }
          object "base_cluster" : opt
          {
              array "may_replace"
              {
                  block_reference "<any array element>" : opt
              }
              int "num_clusters"<1-*>
              int "cluster_radius"<0-*>
          }
          array "may_grow_on" : opt
          {
              block_reference "<any array element>"
          }
          array "may_grow_through" : opt
          {
              block_reference "<any array element>"
          }
          object "acacia_trunk" : opt
          {
              int "trunk_width"
              object "trunk_height"
              {
                  int "base"<1-*>
                  array "intervals" : opt
                  {
                      int "<any array element>"<1-*> : opt
                  }
              }
              object "trunk_lean"
              {
                  bool "allow_diagonal_growth"
                   "lean_height"
                   "lean_steps"
              }
              block_reference "trunk_block"
              object "branches" : opt
              {
                   "branch_length"
                   "branch_position"
                  chance_information "branch_chance"
                  object "branch_canopy" : opt
                  {
                      object "acacia_canopy" : opt
                      {
                          int "canopy_size"<1-*>
                          block_reference "leaf_block"
                          bool "simplify_canopy" : opt
                      }
                      object "canopy" : opt
                      {
                          object "canopy_offset"
                          {
                              int "min"
                              int "max"
                          }
                          int "min_width"<0-*> : opt
                          object "canopy_slope" : opt
                          {
                              int "rise"<1-*> : opt
                              int "run"<1-*> : opt
                          }
                          chance_information "variation_chance" : opt
                          array "variation_chance" : opt
                          {
                              chance_information "<any array element>" : opt
                          }
                          block_reference "leaf_block"
                          object "canopy_decoration" : opt
                          {
                              chance_information "decoration_chance"
                              block_reference "decoration_block" : opt
                              int "num_steps" : opt
                              enumerated_value "step_direction"<"down", "up", "out", "away"> : opt
                          }
                      }
                      object "fancy_canopy" : opt
                      {
                          int "height"<1-*>
                          int "radius"<0-*>
                          block_reference "leaf_block"
                      }
                      object "mega_canopy" : opt
                      {
                           "canopy_height"
                          int "base_radius"<0-*>
                          int "core_width"<1-*> : opt
                          bool "simplify_canopy" : opt
                          block_reference "leaf_block"
                      }
                      object "mega_pine_canopy" : opt
                      {
                           "canopy_height"
                          int "base_radius"<0-*>
                          float "radius_step_modifier"<0.000000-*>
                          int "core_width"<1-*> : opt
                          block_reference "leaf_block"
                      }
                      object "pine_canopy" : opt
                      {
                           "canopy_height"
                          int "base_radius"<1-*>
                          block_reference "leaf_block"
                      }
                      object "roofed_canopy" : opt
                      {
                          int "canopy_height"<3-*>
                          int "core_width"<1-*>
                          int "outer_radius"<0-*>
                          int "inner_radius"<0-*>
                          block_reference "leaf_block"
                      }
                      object "spruce_canopy" : opt
                      {
                           "lower_offset"
                           "upper_offset"
                           "max_radius"
                          block_reference "leaf_block"
                      }
                  }
              }
              object "trunk_decoration" : opt
              {
                  chance_information "decoration_chance"
                  block_reference "decoration_block" : opt
                  int "num_steps" : opt
                  enumerated_value "step_direction"<"down", "up", "out", "away"> : opt
              }
          }
          object "fallen_trunk" : opt
          {
               "log_length"
               "stump_height" : opt
               "height_modifier" : opt
              block_reference "trunk_block"
              feature_reference "log_decoration_feature" : opt
              object "trunk_decoration" : opt
              {
                  chance_information "decoration_chance"
                  block_reference "decoration_block" : opt
                  int "num_steps" : opt
                  enumerated_value "step_direction"<"down", "up", "out", "away"> : opt
              }
          }
          object "fancy_trunk" : opt
          {
              object "trunk_height"
              {
                  int "base"<1-*>
                  int "variance"<1-*>
                  float "scale"
              }
              int "trunk_width"<1-*>
              object "branches"
              {
                  float "slope"
                  float "density"
                  float "min_altitude_factor"<0.000000-1.000000>
              }
              block_reference "trunk_block" : opt
              float "width_scale"<0.000000-*>
              float "foliage_altitude_factor"<0.000000-1.000000>
          }
          object "mega_trunk" : opt
          {
              int "trunk_width"
              object "trunk_height"
              {
                  int "base"<1-*>
                  array "intervals" : opt
                  {
                      int "<any array element>"<1-*> : opt
                  }
              }
              block_reference "trunk_block"
              object "trunk_decoration" : opt
              {
                  chance_information "decoration_chance"
                  block_reference "decoration_block" : opt
                  int "num_steps" : opt
                  enumerated_value "step_direction"<"down", "up", "out", "away"> : opt
              }
              object "branches" : opt
              {
                  int "branch_length"<1-*>
                  float "branch_slope"
                   "branch_interval"
                  object "branch_altitude_factor"
                  {
                      float "min"<0.000000-1.000000>
                      float "max"<0.000000-1.000000>
                  }
                  object "branch_canopy" : opt
                  {
                      object "acacia_canopy" : opt
                      {
                          int "canopy_size"<1-*>
                          block_reference "leaf_block"
                          bool "simplify_canopy" : opt
                      }
                      object "canopy" : opt
                      {
                          object "canopy_offset"
                          {
                              int "min"
                              int "max"
                          }
                          int "min_width"<0-*> : opt
                          object "canopy_slope" : opt
                          {
                              int "rise"<1-*> : opt
                              int "run"<1-*> : opt
                          }
                          chance_information "variation_chance" : opt
                          array "variation_chance" : opt
                          {
                              chance_information "<any array element>" : opt
                          }
                          block_reference "leaf_block"
                          object "canopy_decoration" : opt
                          {
                              chance_information "decoration_chance"
                              block_reference "decoration_block" : opt
                              int "num_steps" : opt
                              enumerated_value "step_direction"<"down", "up", "out", "away"> : opt
                          }
                      }
                      object "fancy_canopy" : opt
                      {
                          int "height"<1-*>
                          int "radius"<0-*>
                          block_reference "leaf_block"
                      }
                      object "mega_canopy" : opt
                      {
                           "canopy_height"
                          int "base_radius"<0-*>
                          int "core_width"<1-*> : opt
                          bool "simplify_canopy" : opt
                          block_reference "leaf_block"
                      }
                      object "mega_pine_canopy" : opt
                      {
                           "canopy_height"
                          int "base_radius"<0-*>
                          float "radius_step_modifier"<0.000000-*>
                          int "core_width"<1-*> : opt
                          block_reference "leaf_block"
                      }
                      object "pine_canopy" : opt
                      {
                           "canopy_height"
                          int "base_radius"<1-*>
                          block_reference "leaf_block"
                      }
                      object "roofed_canopy" : opt
                      {
                          int "canopy_height"<3-*>
                          int "core_width"<1-*>
                          int "outer_radius"<0-*>
                          int "inner_radius"<0-*>
                          block_reference "leaf_block"
                      }
                      object "spruce_canopy" : opt
                      {
                           "lower_offset"
                           "upper_offset"
                           "max_radius"
                          block_reference "leaf_block"
                      }
                  }
              }
          }
          object "trunk" : opt
          {
               "trunk_height"
               "height_modifier" : opt
              block_reference "trunk_block"
              object "trunk_decoration" : opt
              {
                  chance_information "decoration_chance"
                  block_reference "decoration_block" : opt
                  int "num_steps" : opt
                  enumerated_value "step_direction"<"down", "up", "out", "away"> : opt
              }
          }
          object "acacia_canopy" : opt
          {
              int "canopy_size"<1-*>
              block_reference "leaf_block"
              bool "simplify_canopy" : opt
          }
          object "canopy" : opt
          {
              object "canopy_offset"
              {
                  int "min"
                  int "max"
              }
              int "min_width"<0-*> : opt
              object "canopy_slope" : opt
              {
                  int "rise"<1-*> : opt
                  int "run"<1-*> : opt
              }
              chance_information "variation_chance" : opt
              array "variation_chance" : opt
              {
                  chance_information "<any array element>" : opt
              }
              block_reference "leaf_block"
              object "canopy_decoration" : opt
              {
                  chance_information "decoration_chance"
                  block_reference "decoration_block" : opt
                  int "num_steps" : opt
                  enumerated_value "step_direction"<"down", "up", "out", "away"> : opt
              }
          }
          object "fancy_canopy" : opt
          {
              int "height"<1-*>
              int "radius"<0-*>
              block_reference "leaf_block"
          }
          object "mega_canopy" : opt
          {
               "canopy_height"
              int "base_radius"<0-*>
              int "core_width"<1-*> : opt
              bool "simplify_canopy" : opt
              block_reference "leaf_block"
          }
          object "mega_pine_canopy" : opt
          {
               "canopy_height"
              int "base_radius"<0-*>
              float "radius_step_modifier"<0.000000-*>
              int "core_width"<1-*> : opt
              block_reference "leaf_block"
          }
          object "pine_canopy" : opt
          {
               "canopy_height"
              int "base_radius"<1-*>
              block_reference "leaf_block"
          }
          object "roofed_canopy" : opt
          {
              int "canopy_height"<3-*>
              int "core_width"<1-*>
              int "outer_radius"<0-*>
              int "inner_radius"<0-*>
              block_reference "leaf_block"
          }
          object "spruce_canopy" : opt
          {
               "lower_offset"
               "upper_offset"
               "max_radius"
              block_reference "leaf_block"
          }
      }
      object "minecraft:weighted_random_feature" : opt
      {
          object "description"
          {
              string "identifier" // The name of this feature in the form 'namespace_name:feature_name'. 'feature_name' must match the filename.
          }
          array "features"[1,*]
          {
              array "<any array element>"[2] : opt // Collection of weighted features that placement will select from.
              {
                  feature_reference "[0..0]" // Named reference to a feature.
                  float "[1..1]" // Weight used in random selection. Value is relative to other weights in the collection.
              }
          }
      }
  }




Attaching features

Features must be attached to at least one biome in order to show up in the world. During world generation, biomes attempt to place their attached features chunk-by-chunk. Features can be attached in two ways:
1) Via a feature rule definition
2) Via the "minecraft:forced_features" biome component
Back to top

Feature rules

Feature rules are separate JSON definition files found in the "feature_rules" subfolder of behavior packs. Feature rules follow the same filename rules as features. Each feature rule controls exactly one feature and serves as the root of a chain of feature data. To attach a feature to a biome with a feature rule, the "conditions" object must include the "minecraft:biome_filter" field. This is a list of filter tests that are performed on each biome to determine if the feature should be attached. Most relevant is the "has_biome_tag" test.

Here is a sample feature rule
{
  "format_version": "1.13.0",
  "minecraft:feature_rules": {
    "description": {
      "identifier": "minecraft:birch_forest_surface_trees_feature",
      "places_feature": "minecraft:legacy:birch_forest_tree_feature"
    },
    "conditions": {
      "placement_pass": "surface_pass",
      "minecraft:biome_filter": [
        {
          "test": "has_biome_tag",
          "operator": "==",
          "value": "forest"
        },
        {
          "all_of": [
            {
              "test": "has_biome_tag",
              "operator": "==",
              "value": "birch"
            },
            {
              "test": "has_biome_tag",
              "operator": "!=",
              "value": "mutated"
            }
          ]
        }
      ]
    },
    "distribution": {
      "iterations": 1,
      "x": 0,
      "y": 0,
      "z": 0
    }
  }
}

Back to top

Feature rule schema


  {
      version "format_version"
      object "minecraft:feature_rules"
      {
          object "description"
          {
              string "identifier" // The name of this feature rule in the format 'namespace_name:rule_name'. 'rule_name' must match the filename.
              feature_reference "places_feature" // Named reference to the feature controlled by this rule.
          }
          object "conditions" // Parameters to control where and when the feature will be placed.
          {
              enumerated_value "placement_pass"<"first_pass", "before_underground_pass", "underground_pass", "after_underground_pass", "before_surface_pass", "surface_pass", "after_surface_pass", "before_sky_pass", "sky_pass", "after_sky_pass", "final_pass"> // When the feature should be placed relative to others. Earlier passes in the list are guaranteed to occur before later passes. Order is not guaranteed within each pass.
              biome_filter_group "minecraft:biome_filter" : opt // List of filter tests to determine which biomes this rule will attach to.
          }
          object "distribution" // Parameters controlling the initial scatter of the feature.
          {
              molang "iterations" // Number of scattered positions to generate
              object "scatter_chance" : opt // Probability numerator / denominator that this scatter will occur.  Not evaluated each iteration; either no iterations will run, or all will.
              {
                  int "numerator"<1-*>
                  int "denominator"<1-*>
              }
              molang "scatter_chance" : opt // Probability (0-100] that this scatter will occur.  Not evaluated each iteration; either no iterations will run, or all will.
              enumerated_value "coordinate_eval_order"<"xyz", "xzy", "yxz", "yzx", "zxy", "zyx"> : opt // The order in which coordinates will be evaluated. Should be used when a coordinate depends on another. If omitted, defaults to "xzy".
              molang "x" : opt // Expression for the coordinate (evaluated each iteration).  Mutually exclusive with random distribution object below.
              object "x" : opt // Distribution for the coordinate (evaluated each iteration).  Mutually exclusive with Molang expression above.
              {
                  enumerated_value "distribution"<"uniform", "gaussian", "inverse_gaussian", "fixed_grid", "jittered_grid"> // Type of distribution - uniform random, gaussian (centered in the range), or grid (either fixed-step or jittered)
                  int "step_size"<1-*> : opt // When the distribution type is grid, defines the distance between steps along this axis
                  int "grid_offset"<0-*> : opt // When the distribution type is grid, defines the offset along this axis
                  array "extent"[2]
                  {
                      molang "[0..0]" : opt // Lower bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                      molang "[1..1]" : opt // Upper bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                  }
              }
              molang "z" : opt // Expression for the coordinate (evaluated each iteration).  Mutually exclusive with random distribution object below.
              object "z" : opt // Distribution for the coordinate (evaluated each iteration).  Mutually exclusive with Molang expression above.
              {
                  enumerated_value "distribution"<"uniform", "gaussian", "inverse_gaussian", "fixed_grid", "jittered_grid"> // Type of distribution - uniform random, gaussian (centered in the range), or grid (either fixed-step or jittered)
                  int "step_size"<1-*> : opt // When the distribution type is grid, defines the distance between steps along this axis
                  int "grid_offset"<0-*> : opt // When the distribution type is grid, defines the offset along this axis
                  array "extent"[2]
                  {
                      molang "[0..0]" : opt // Lower bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                      molang "[1..1]" : opt // Upper bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                  }
              }
              molang "y" : opt // Expression for the coordinate (evaluated each iteration).  Mutually exclusive with random distribution object below.
              object "y" : opt // Distribution for the coordinate (evaluated each iteration).  Mutually exclusive with Molang expression above.
              {
                  enumerated_value "distribution"<"uniform", "gaussian", "inverse_gaussian", "fixed_grid", "jittered_grid"> // Type of distribution - uniform random, gaussian (centered in the range), or grid (either fixed-step or jittered)
                  int "step_size"<1-*> : opt // When the distribution type is grid, defines the distance between steps along this axis
                  int "grid_offset"<0-*> : opt // When the distribution type is grid, defines the offset along this axis
                  array "extent"[2]
                  {
                      molang "[0..0]" : opt // Lower bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                      molang "[1..1]" : opt // Upper bound (inclusive) of the scatter range, as an offset from the input point to scatter around
                  }
              }
          }
      }
  }


Back to top

Forced features

Features attached with the second method are called "forced" or "explicit" features. Unlike feature rules, forced features are not defined in separate JSON files. Instead, they are specified in the existing biome JSON definitions via the "minecraft:forced_features" component. Like feature rules, this component includes fields that define when features should be placed ("placement_pass") and how they should be scattered ("distribution"). For more information about biome components (including the complete JSON schema), consult the biome documentation.
Back to top