Creating a Feature from Scratch

This guide will outline the process of creating a new feature from the beginning with adding grass.

If you haven’t already, please read the Config Development Introduction & Creating A Pack From Scratch for more information before continuing.

For a more detailed and in-depth guide about creating a new feature from scratch, please read this unofficial development guide, Feature Config.

If you’re stuck or need an example, you can find reference config packs for this guide on the GitHub repo.

Setting up a New Feature

PROCEDURE

1. Add feature stage(s)

Feature generation is divided up into generation stages. Your pack will need to define at least one generation stage in order to generate any features.

Open your pack manifest in your editor of choice.

Add the generation-stage-feature addon as a dependency, using versions 1.+.

This addon will allow us to create new generation stages for features within the pack manifest.

pack.yml
1id: YOUR_PACK_ID
2version: 0.4.0
3
4addons:
5  ...
6  generation-stage-feature: "1.+"

Add the highlighted lines below to your pack manifest to create the generation stage.

pack.yml
1id: YOUR_PACK_ID
2
3...
4
5stages:
6  - id: flora
7    type: FEATURE

Important

The generation stage ids can be named to your liking and generation stages will generate in order from top to bottom.

2. Create your feature config

Add the config-feature addon to the pack manifest, using versions 1.+.

This addon will allow us to create feature config files.

pack.yml
1id: YOUR_PACK_ID
2version: 0.4.0
3
4addons:
5  ...
6  config-feature: "1.+"

Create a blank config file with the file name grass_feature.yml.

Set the config type via the type parameter, and config id as shown below.

grass_feature.yml
1id: GRASS_FEATURE
2type: FEATURE

3. Add the feature distributor

Distributors determine the x-axis and z-axis placement of a feature in the world.

Add the config-distributors addon to the pack manifest, using versions 1.+.

This addon provides a set of distributors to use within feature config files.

pack.yml
1id: YOUR_PACK_ID
2version: 0.4.0
3
4addons:
5  ...
6  config-distributors: "1.+"

Configure the grass_feature.yml config to utilize the POSITIVE_WHITE_NOISE distributor type as shown below.

grass_feature.yml
1id: GRASS_FEATURE
2type: FEATURE
3
4distributor:
5  type: SAMPLER
6  sampler:
7    type: POSITIVE_WHITE_NOISE
8  threshold: 0.25

Note

Documentation of distributor types can be found here.

Documentation of POSITIVE_WHITE_NOISE and other noise samplers can be found here.

4. Add the feature locator

Locators determine the y-axis placement of a feature in the world.

Add the config-locators addon to the pack manifest, using versions 1.+.

This addon provides a set of locators to use within feature config files.

pack.yml
1id: YOUR_PACK_ID
2version: 0.4.0
3
4addons:
5  ...
6  config-locators: "1.+"

Configure the grass_feature.yml config to utilize the SURFACE locator type as shown below.

grass_feature.yml
 1id: GRASS_FEATURE
 2type: FEATURE
 3
 4distributor:
 5  ...
 6
 7locator:
 8  type: SURFACE
 9  range:
10    min: 0
11    max: 319

The SURFACE locator type will place the feature above any block with air above it.

Each locator will typically require the range that it can check.

range has min (minimum) and a max (maximum) parameters.

Note

Documentation of the various locator types available can be found here.

5. Improve feature locator

The SURFACE locator is handy for placing features on top of blocks, but it doesn’t check the block it places the feature upon.

Utilizing the AND locator, we can use multiple locators for stricter criteria for where the feature can generate.

Using the PATTERN locator with the type specified to use MATCH_SET will allow us to specify the blocks that must match in order to generate the feature.

Add the highlighted lines below to add the additional locator.

feature.yml
 1id: GRASS_FEATURE
 2type: FEATURE
 3
 4distributor:
 5  ...
 6
 7locator:
 8  type: AND
 9  locators:
10    - type: SURFACE
11      range: &range  #range values anchored for other locators to use
12        min: 0
13        max: 319
14    - type: PATTERN
15      range: *range  #references previously anchored range values
16      pattern:
17        type: MATCH_SET
18        blocks:
19          - minecraft:grass_block
20          - minecraft:dirt
21        offset: -1

The AND locator list contains both the SURFACE and PATTERN locators with the range anchored in SURFACE being referenced by the range in PATTERN.

The PATTERN locator with the MATCH_SET type consists of the parameters blocks and offset.

  • blocks - List of blocks that must match in order to generate the feature

  • offset - The y-level offset of the checked block

The blocks minecraft:grass_block and minecraft:dirt will suffice with an offset of -1 to check the block that is specifically right underneath the feature.

6. Add the structure

The structure-block-shortcut addon will provide the capability to use a shortcut within structure distribution to directly place a block rather than having to create an entire structure file for just a single block.

Add the structure-block-shortcut addon to the pack manifest, using versions 1.+.

pack.yml
1id: YOUR_PACK_ID
2version: 0.4.0
3
4addons:
5  ...
6  structure-block-shortcut: "1.+"

We will now utilize the structure-block-shortcut addon that was added above to easily define single blocks rather than a structure.

Note

Versions prior to 1.20.3 will need to use minecraft_grass.

grass_feature.yml
 1id: GRASS_FEATURE
 2type: FEATURE
 3
 4distributor:
 5  ...
 6
 7locator:
 8  ...
 9
10structures:
11  distribution:
12    type: CONSTANT
13  structures: BLOCK:minecraft:short_grass

The structures parent key consists of the nested parameters structures.structures and structures.distribution.

structures.structures determines the structure or weighted list of structures to select from upon feature generation in the world.

structures.distribution determines the noise sampler that influences the structure selection results.

Tip

Features can select from a weighted list of structures or blocks in this particular case with a noise sampler to guide the structure selection as shown below.

feature.yml
1structures:
2  distribution:
3    type: WHITE_NOISE
4    salt: 4357
5  structures:
6    - BLOCK:minecraft:poppy: 1
7    - BLOCK:minecraft:blue_orchid: 1
8    - BLOCK:minecraft:dandelion: 1

Weighted lists covered in detail here.

6. Apply feature to biome

We’ll now add the grass feature to FIRST_BIOME.

Add the highlighted lines below to the FIRST_BIOME config.

first_biome.yml
 1id: FIRST_BIOME
 2type: BIOME
 3
 4vanilla: minecraft:plains
 5
 6...
 7
 8features:
 9  flora:
10    - GRASS_FEATURE

The GRASS_FEATURE should now generate grass in FIRST_BIOME.

Tip

Multiple generation stages in biome configs will be done as shown below:

first_biome.yml
 1id: FIRST_BIOME
 2type: BIOME
 3
 4...
 5
 6features:
 7  flora:
 8    - GRASS_FEATURE
 9  trees:
10    - OAK_TREES

7. Load your pack

At this stage, your pack should now be capable of generating grass! You can load up your pack by starting your development client / server which contains the pack you have just defined. You can confirm that your pack has loaded if the pack id (as specified in the pack manifest) appears when using the /packs command, or in your console when starting the server / client up.

If for whatever reason your pack does not load, an error message will show up in console explaining why the pack has failed to load, please read through any of these errors and try to interpret what you may have done wrong, and follow through the previous steps again carefully.

If you still are unable to load the pack, feel free to contact us with any relevant errors.

Conclusion

Once you have verified your pack has loaded correctly, you can now generate a world with grass using features!

Reference configurations for this guide can be found on GitHub here.

../../../_images/first-biome-grass.png