Skip to content

Instantly share code, notes, and snippets.

@TelepathicGrunt
Last active February 11, 2024 20:02
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TelepathicGrunt/b768ce904baa4598b21c3ca42f137f23 to your computer and use it in GitHub Desktop.
Save TelepathicGrunt/b768ce904baa4598b21c3ca42f137f23 to your computer and use it in GitHub Desktop.

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 forge: namespace and the c: namespace.

For best compatibility with any mod or datapack, you should have a custom tag that pulls entries from minecraft:, forge:, and c: tags. Yes, datapacks too should be adding their biomes to the forge: and 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 mods, use the c: biome tags from Fabric API. See this link for a list of their tags and what they contain:

https://github.com/FabricMC/fabric/tree/1.19.2/fabric-convention-tags-v1/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. Try and use these biome tags if making a Forge mod: https://github.com/MinecraftForge/MinecraftForge/tree/1.19.x/src/generated/resources/data/forge/tags/worldgen/biome

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


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.

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();
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment