Skip to content

Instantly share code, notes, and snippets.

@misode
Last active May 15, 2023 00:18
Show Gist options
  • Save misode/45559d34627755ecaa52497daea83544 to your computer and use it in GitHub Desktop.
Save misode/45559d34627755ecaa52497daea83544 to your computer and use it in GitHub Desktop.

Custom data pack structures in 1.18.2

This guide will showcase how to create a data pack that adds a custom structure to the world. There is also a data pack download of this complete example.

Always leave the world and rejoin to apply the new changes!

⚠️ This guide has moved ⚠️

Updates for both 1.18.2 and 1.19 can be found at https://misode.github.io/guides/adding-custom-structures/

Pack.mcmeta

Like every data pack, we need a pack.mcmeta. In this version, the pack format is 9!

{
  "pack": {
    "pack_format": 9,
    "description": "A tall tower"
  }
}

The structure set

A structure set is where the placement starts. It defines where in the world the structure should be placed, and how rare it is. It takes a weighted list of different structures, allowing structure variants (for example the vanilla nether has a structure set with both the bastion and fortress).

data/example/worldgen/structure_set/tall_towers.json

{
  "structures": [
    {
      "structure": "example:tall_tower",
      "weight": 1
    }
  ],
  "placement": {
    "type": "minecraft:random_spread",
    "spacing": 5,
    "separation": 2,
    "salt": 1646207470
  }
}

Structure sets are made up of two parts:

  • structures: A weighted list of configured structure features (see next step).
  • placement: The structure placement
    • placement.type: Either random_spread or concentric_rings. The latter is only used by strongholds in vanilla, so we'll focus on random_spread
    • placement.spacing: Roughly the average distance in chunks between two structures in this set.
    • placement.separation: The minimum distance in chunks. Needs to be smaller than spacing.
    • placement.salt: A random number that is combined with the world seed. Always use a different random number for different structures, otherwise they will end up being placed in the same spot!

When using the random_spread placement type, it generates structures grid-based. Here's an illustration of the above example with spacing = 5, separation = 2. There will be one structure attempt in each 5x5 chunk grid, and only at X a structure can spawn.

.............
..XXX..XXX..X
..XXX..XXX..X
..XXX..XXX..X
.............
.............
..XXX..XXX..X
..XXX..XXX..X
..XXX..XXX..X

The configured structure

The configured structure (feature) is the ID you will be able to reference in /locate.

data/example/worldgen/configured_structure_feature/tall_tower.json

{
  "type": "minecraft:village",
  "config": {
    "start_pool": "example:tall_tower",
    "size": 1
  },
  "biomes": "#minecraft:has_structure/mineshaft",
  "adapt_noise": true,
  "spawn_overrides": {}
}

Let's go over all the fields.

  • type: This is the structure feature type. When making custom structures, you almost always want to set this to village or bastion_remnant. There is one important difference between the two: using village will spawn the structure on the surface, while bastion_remnant will always spawn the structure at Y=33.
  • config.start_pool: This is a reference to the template pool (see next step).
  • config.size: This is a number between 1 and 7. This is important if your structure uses jigsaw. In this simple example, we'll leave it at 1.
  • biomes: This controls in which biomes this structure is allowed to generate. You can give it any biome tag, a list of biomes, or a single biome. For easy testing we'll set it to every biome with mineshafts.
  • adapt_noise: When true, it will add extra terrain below each structure piece.
  • spawn_overrides: This field allows you to override mob spawning inside the structure bounding boxes. This is currently outside the scope of this guide, but you could look at the vanilla monument structure feature as a reference.

The template pool

The template pool defines how to build up your structure. Since we're not using jigsaw, this is quite straight forward: we want to place a single NBT structure.

data/example/worldgen/template_pool/tall_tower.json

{
  "name": "example:tall_tower",
  "fallback": "minecraft:empty",
  "elements": [
    {
      "weight": 1,
      "element": {
        "element_type": "minecraft:single_pool_element",
        "location": "example:stone_tall_tower",
        "projection": "rigid",
        "processors": "minecraft:empty"
      }
    }
  ]
}

Again, let's go over the fields:

  • name: For some reason, the game needs the name of this template pool. Just set this to the ID of the template pool.
  • fallback: Used in jigsaw structures, but we can simply use minecraft:empty.
  • elements: A weighted list of pool elements to choose from. You can add multiple elements here if your structure has different starting structure files. For example in vanilla a plains village has different town center variants.
    • element_type: The type of this element. One of empty_pool_element (placing nothing), feature_pool_element (placing a placed feature), legacy_single_pool_element, list_pool_element, and single_pool_element (placing a structure).
    • location: The path to the structure NBT file. (see next step).
    • projection: Either rigid or terrain_matching. Use the latter if you want the structure to match the terrain, just like village paths do.
    • processors: If you want to run any processor lists, this is quite complicated so again we'll skip this for now and set it to minecraft:empty.

The structure

Creating the structure NBT file is entirely up to you. In this example I'm going to use a tower structure from Gamemode 4.

data/example/structures/stone_tall_tower.nbt

(binary NBT file) Download the structure from this example

Result

stone tower close-up a bunch of towers in a forest

@Gamingbarn
Copy link

Gamingbarn commented Apr 3, 2022

I have a question. Im trying to make a datapack with a custom dimension for my smp, and me and my friends made a structure for it to spawn. I have everything done, and it works. But is there any way to put the structure a couple of blocks in the ground. Because below the structure, there is redstone, and we covered this up with black concrete. But the black concrete spawns above the ground. How can i put the black concrete with the redstone below the ground

You'll have to use jigsaws for that.
https://gist.github.com/GentlemanRevvnar/387f9ee28613715c187a36dbc1dff35d
I follow this tutorial, it's very helpful.
@RobotLuca37

@Syhix
Copy link

Syhix commented Apr 6, 2022

Tutorial on version 1.19 planned?

@kittech0
Copy link

kittech0 commented Apr 7, 2022

how could i generate structures under water?

@misode
Copy link
Author

misode commented Apr 7, 2022

how could i generate structures under water?

@JustFoxx You can do this, but only in the 1.19 snapshots. There is a field project_start_to_heightmap that allows you to configure the heightmap that the structure should spawn at, one option is OCEAN_FLOOR_WG. For example: https://misode.github.io/worldgen/structure/?share=3ac3e684-b360-413d-8d9b-3be17f106fdc

@Syhix
Copy link

Syhix commented Apr 12, 2022

When I try to spawn a cat with spawn_overrides it doesn't work. This is exactly the same configuration as swamp_hut.

"spawn_overrides": {
        "creature": {
            "bounding_box": "piece",
            "spawns": [
                {
                    "type": "minecraft:cat",
                    "weight": 1,
                    "minCount": 1,
                    "maxCount": 1
                }
            ]
        }
    }

@rzerdik
Copy link

rzerdik commented May 5, 2022

I was pretty sure that I did everything correctly but the pack wont validate in the world creation menu. I originally wanted it toonly generate in the plains biome, but I dont know how to specify that yet, so I used the "#minecraft:has_structure/mineshaft" from the example. would anyone be so kind and look over it? (theres also other stuff in the pack but I dont think that it fucks with anything)

https://www.mediafire.com/file/h76206qwv5yallx/items%252B.zip/file

your zip file contains also folder with the same name as the zip, it's because you ziped the folder, not it's contents.
you have this structure:

.zip

  • item+
    • data
    • pack.mcmeta

instead, it should be:

.zip

  • data
  • pack.mcmeta

@fishh333
Copy link

fishh333 commented May 5, 2022

Thanks but I only zipped it at all so I could upload it. I did the testing without ever tipping it and it still failed to validate

PS: Also validating isn't the same as showing up in the datapack selection

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment