Creating a Feature with a Structure From Scratch

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

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 Structure

PROCEDURE

1. Create your structure file

Structure files can either be dynamic TerraScript .tesf or static schematic .schem files.

TerraScript files are written in the TerraScript Language. TerraScript allows for procedurally generated structures and unique complex structure layouts.

  1. Add the structure-terrascript-loader addon to the pack manifest, using versions 1.+

pack.yml
1id: YOUR_PACK_ID
2version: 0.5.0
3
4addons:
5  ...
6  structure-terrascript-loader: "1.+"
  1. Create a blank .tesf file.

  2. Add TerraScript within the .tesf file to generate the structure.

oak_tree.tesf will be the example file name used for this guide.

A barebones sample oak_tree.tesf file has been provided below if you need it.

oak_tree.tesf
1block(0, 0, 0, "minecraft:oak_log", true);
2block(0, 1, 0, "minecraft:oak_leaves", false);

Schematic files consist of an arrangement of blocks that make up a structure that can be saved through WorldEdit.

  1. Add the structure-sponge-loader addon to the pack manifest, using versions 1.+

pack.yml
1id: YOUR_PACK_ID
2version: 0.5.0
3
4addons:
5  ...
6  structure-sponge-loader: "1.+"
  1. Source a .schem file, these can be created using WorldEdit if you wish to create your own.

  2. Add the .schem file to your pack.

oak_tree.schem will be the example file name used for this guide.

A sample oak_tree.schem can be found on GitHub if needed.

Warning

If you decide to try out both structure file types, be sure to name them differently as you can’t have structure files with the same name.

2. Create new generation stage

It’s best to categorize feature into different stages to not only keep feature organization tidy, but to allow particular features to generate before others.

For example, you may want to generate trees before grass, so trees aren’t blocked from generating by the grass.

We will now utilize the generation-stage-feature addon that was added in Setting up a New Feature to create a new generation stage.

pack.yml
 1id: YOUR_PACK_ID
 2
 3...
 4
 5stages:
 6  - id: trees
 7    type: FEATURE
 8  # The trees generation stage will come before flora, making it generate first.
 9  - id: flora
10    type: FEATURE

Important

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

3. Create your feature config

We will now utilize the config-feature addon that was added in Setting up a New Feature to create a new feature config file.

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

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

oak_tree_feature.yml
1id: OAK_TREE_FEATURE
2type: FEATURE

4. Add the feature distributor

We will now utilize the config-distributors addon that was added in Setting up a New Feature to add the distributor.

Configure oak_tree_feature.yml to utilize the PADDED_GRID distributor type as shown below.

oak_tree_feature.yml
1id: OAK_TREE_FEATURE
2type: FEATURE
3
4distributor:
5  type: PADDED_GRID
6  width: 12
7  padding: 4
8  salt: 5864

The PADDED_GRID distributor type utilizes cells in a grid with the feature placed within each cell with padding between each cell to ensure that features don’t generate too close to one another.

PADDED_GRID utilizes the nested parameters width, padding, and salt.

  • Width - Determines the size of each cell that will contain your feature.

  • Padding - Determines the gap between each cell.

  • Salt - Typically a random number that offsets the distributor results to prevent feature placement overlap with the same distributor type. Salt function covered in detail here.

../../../_images/paddedgrid.png

Note

Documentation of PADDED_GRID and other distributor types can be found here.

5. Add the feature locator

We will now utilize the config-locators addon that was added in Setting up a New Feature to add the locator.

Configure oak_tree_feature.yml to utilize the TOP locator type as shown below.

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

The TOP locator type will place the feature on the block located at the highest y-level rather than every block with air above it with the SURFACE locator.

Note

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

6. Improve feature locator

Just like with the SURFACE locator when adding short grass, the TOP locator is handy for placing features at the highest block, 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: OAK_TREE_FEATURE
 2type: FEATURE
 3
 4distributor:
 5  ...
 6
 7locator:
 8  type: AND
 9  locators:
10    - type: TOP
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

7. Add the structure

You can now add your structure to the oak_tree_feature config with the highlighted lines below.

oak_tree_feature.yml
 1id: OAK_TREE_FEATURE
 2type: FEATURE
 3
 4distributor:
 5  ...
 6
 7locator:
 8  ...
 9
10structures:
11  distribution:
12    type: CONSTANT
13  structures: oak_tree

Tip

Features can select from a weighted list of structures 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    - oak_tree_1: 1
7    - oak_tree_2: 1
8    - oak_tree_3: 1

Weighted lists covered in detail here.

8. Apply feature to biome

We’ll now add the tree 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  trees:
10    - OAK_TREE_FEATURE
11  flora:
12    - GRASS_FEATURE

The OAK_TREE_FEATURE feature should now generate your oak tree structures in FIRST_BIOME.

9. Load your pack

At this stage, your pack should now be capable of generating oak trees! 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 oak tree structures using features!

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

../../../_images/trees-tesf.png ../../../_images/trees-schem.png