The following applies to 1.16.2 at the time this is written.
RegistryKey<Biome>for most operations, since it will be stable even across world and datapack reloads
IdentityHashMap<RegistryKey<Biome>, YourCustomData>in your mod, and query the custom data based on the biome's key.
DynamicRegistryManagerof the current world,
ServerWorldoffer a convenience method for this called
method_31081(currently unnamed), which retrieves the key of the biome at a given
BlockPos, although you can also do this yourself via
FabricBiomes#addSpawnBiomewas removed, since this is now a property that can be set via Vanilla's
AddHillsLayer#field_26727based on their raw ids. Since the mapping is from unmodified biome → modified biome, there's no real point in exposing this to mods, because there can only be _one_ modified biome for each unmodified one.
The following diagram shows various objects that participate in defining world generation, and where they are registered/defined.
The general rule of thumb is that
Registry will contain objects that contain some form of custom code, while BuiltInRegistry contains built-in data objects that mostly reference code objects from an associate Registry by ID and sometimes add configuration data.
As an example:
OreFeatureunder the ID
minecraft:ore, and configure it differently (for example
minecraft:ore_ironto place iron ore)
For use in an actual world, all data objects from
BuiltInRegistries will be copied by value into a new
DynamicRegistryManager and may be overridden by JSON files in enabled data packs.
You should register your custom worldgen in the following order in your mod initializer:
Registryor using a specific API (i.e. see fabric-api for structures)