Skip to content

Instantly share code, notes, and snippets.

@TelepathicGrunt
Last active April 13, 2025 13:09
Show Gist options
  • Save TelepathicGrunt/b768ce904baa4598b21c3ca42f137f23 to your computer and use it in GitHub Desktop.
Save TelepathicGrunt/b768ce904baa4598b21c3ca42f137f23 to your computer and use it in GitHub Desktop.

Table of Contents

Biome Tags are awesome!

What tag entries exist that I can use???

Using a tag for structures but exclude some entries in it

How to use in code?


Biome Tags are awesome!

As a result of 1.18.2 changes, all worldgen registries can now have tags. Including biomes! As a result of this, Mojang has deprecated the biome category which means that sooner or later, this enum will be deleted. To better protect yourself and your mod/datapack from relying on these categories, you should instead, switch to using biome tags.

The existing biome tags from vanilla do not cover all usecases which means that many modders have started banding together to decide on common biome tags to use. These common biome tags are under the c: namespace mostly. In Forge 1.18.2 to 1.20.X, they use the forge: namespace but Forge 1.21.X and newer uses c: now.

For best compatibility with any mod or datapack, you should have a custom tag that pulls entries from minecraft: and c: tags. Yes, datapacks too should be adding their biomes to the c: namespaced tags. And mods can "datagen" the tag json files automatically but that is outside the scope of this gist. See the Fabric wiki or Forge Community Wiki for info on how to do datagen in your mod.

Using optional tag entries, you can make sure your own biome tag group will not blow up even when a tag or biome entry doesn't exist. Example of a custom forest biome tag that pulls from all three tags and will not blow up if forge: or c: does not exist when running the game:

{
  "replace": false,
  "values": [
    "#minecraft:is_forest",
    {
      "id": "#forge:is_forest",
      "required": false
    },
    {
      "id": "#c:forest",
      "required": false
    }
  ]
}

NOTE: If you are making a custom dimension with custom biome, be aware that many of these biome tags are utilized by mods or datapacks to add Overworld-styled structures or mobs to biomes. So if you want your dimension to have modded Overworld structures, add your custom biome to the respective biome tags. If not, don't add to the biome tags but make your own biome tag that holds all of your biomes in case some other mod was to grab the biome for a specific mod compat.

What tag entries exist that I can use???

minecraft:

To find a list of all vanilla tags, please see the biome section on Misode's Mcmeta repo here:

https://github.com/misode/mcmeta/tree/data-json/data/minecraft/tags/worldgen/biome


c:

To find all c: tags to work best with Fabric and NeoForge mods, use the c: biome tags from Fabric API or NeoForge. See this link for a list of their tags and what they contain:

https://github.com/neoforged/NeoForge/tree/1.21.x/src/generated/resources/data/c/tags/worldgen/biome

https://github.com/FabricMC/fabric/tree/1.21.5/fabric-convention-tags-v2/src/generated/resources/data/c/tags/worldgen/biome


forge:

Biome tags are the standard now that Mojang is pushing biome tags hard and Forge added Biome Modifiers.

A PR was merged into Forge to try and standardize the biome tags under the forge: namespace for 1.20.1 and below. Try and use these biome tags if making a Forge mod for 1.20.X and below:

https://github.com/MinecraftForge/MinecraftForge/tree/1.20.1/src/generated/resources/data/forge/tags/worldgen/biome

These tags should be utilized in place of hardcoded biome checks if possible.

For 1.21.x+, Forge has switched to c: tags as well:

https://github.com/MinecraftForge/MinecraftForge/tree/1.21.x/src/main/generated/data/c/tags/worldgen/biome


custom?

You are always free to make your own custom tags such as a c:rocky biome tag to try and create a new standard. You should try and make a PR into Fabric or Forge to add the new tags you made into them to help get your new tags to be more visible and utilized by others. Just be sure to follow the same naming style as the other tags under c: or forge:. It is heavily frowned upon to make a new custom tag under the minecraft: namespace so instead, do it under c: or forge: or under your own mod's/datapack's namespace if the tag is for internal use with your mod/datapack.

Using a tag for structures but exclude some entries in it

As a modder:

If you are a modder, you can create a new structure type class with a special codec and holderset. This can allow you to have one tag for the valid biomes and a second tag to filter out the biomes you don't want your structures to spawn in. See this Structure Tutorial Mod for an example:

https://github.com/TelepathicGrunt/StructureTutorialMod/blob/8ba70f02e4979b39061e2478349eaaf0d15f889d/src/main/resources/data/structure_tutorial/worldgen/structure/code_structure_sea_boat.json#L23-L32

As a player/packmaker:

If you are a player/packmaker on Fabric, you are a bit out of luck as Fabric has no filtering option available out of the box. KubeJS mod might have something for this so check with that mod.

If you are on Forge or NeoForge, these modloaders provide an and and not holderset. By overriding the structure JSON file, you can swap the biomes field with something like this. What this is saying is the and block only accepts biomes that matches everything in the list. The first entry is the forest tag. The second entry is a not holderset saying it matches any biome not in the snowy tag. Together, this means this structure will only spawn in forest biomes that are not snowy.

  "biomes": {
    "type": "neoforge:and",
    "values": [
      "#minecraft:is_forest",
      {
        "type": "neoforge:not",
        "value": "#minecraft:is_snowy"
      }
    ]
  },
  //...rest of structure JSON file

How to use in code?

To use biome tags in code, first you will need to create a TagKey. A TagKey is an object that is very similar to a ResourceKey where it is not the actual tag or entry itself but helps you to get it later. To create a TagKey, call TagKey.create at any time but a static field is easiest like so:

public static TagKey<Biome> ALL_DESERTS = 
        TagKey.create(Registry.BIOME_REGISTRY, new ResourceLocation(Mod.MODID, "all_deserts"));

Now to check if a biome is part of a tag, call the .is( method on the biome and pass in the TagKey. That's it.

if (level.getBiome(mutable).is(ModTags.ALL_DESERTS)) {

To get all biomes that have a certain tag, grab the biome registry from the world/level itself and then call .getOrCreateTag( on it while passing in a tagKey. This will return a HolderSet which contains a set of Holder. You can iterate over the set in a for loop and call .value() on each Holder to get the biome object it holds.

Registry<Biome> biomeRegistry = context.level().registryAccess().registryOrThrow(Registry.Biome_REGISTRY);
for (Holder<Biome<?, ?>> biomeHolder : biomeRegistry.getOrCreateTag(ModTags.ALL_DESERTS)) {
  Biome biome = biomeHolder.value();
  ...
@TelepathicGrunt
Copy link
Author

Gist updated a bit now to mention that NeoForge as well uses c tags

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