Skip to main content
Minestom’s registry system manages both static (vanilla) and dynamic (custom) game content like biomes, dimensions, enchantments, and more. Registries provide a centralized way to store and reference game data.

Overview

Registries in Minestom come in two flavors:

Static Registries

Immutable registries for vanilla content (blocks, items, entities, fluids)

Dynamic Registries

Mutable registries for custom content (biomes, dimensions, enchantments)
Use RegistryKey<T> to reference registry entries rather than storing the objects directly. This ensures proper network synchronization and serialization.

Accessing Registries

All registries are accessed through the Registries interface, typically from MinecraftServer or ServerProcess.

Static Registries

Static registries contain vanilla Minecraft content and cannot be modified.
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.Material;

// Get static registries
Registry<Block> blocks = MinecraftServer.getBlockRegistry();
Registry<Material> materials = MinecraftServer.getMaterialRegistry();
Registry<EntityType> entityTypes = MinecraftServer.getEntityTypeRegistry();
Registry<Fluid> fluids = MinecraftServer.getFluidRegistry();

Dynamic Registries

Dynamic registries allow registration of custom content.
Registries registries = MinecraftServer.process();

// World registries
DynamicRegistry<Biome> biomes = registries.biome();
DynamicRegistry<DimensionType> dimensions = registries.dimensionType();

// Item registries
DynamicRegistry<Enchantment> enchantments = registries.enchantment();
DynamicRegistry<TrimMaterial> trimMaterials = registries.trimMaterial();
DynamicRegistry<TrimPattern> trimPatterns = registries.trimPattern();

RegistryKey

A RegistryKey<T> is a reference to a registry entry, containing the entry’s namespaced key.

Creating Registry Keys

// Register returns a RegistryKey
Biome customBiome = Biome.builder()
    .temperature(0.8f)
    .downfall(0.4f)
    .build();

RegistryKey<Biome> biomeKey = 
    MinecraftServer.getBiomeRegistry().register("myplugin:desert", customBiome);

Using Registry Keys

key()
Key
Gets the namespaced key
Key key = registryKey.key();
String namespace = key.namespace(); // "minecraft" or "myplugin"
String value = key.value();         // "plains", "desert", etc.
name()
String
Gets the full key as a string
String name = biomeKey.name(); // "myplugin:desert"

DynamicRegistry

Dynamic registries support registration, modification, and removal of entries.

Registration

register(id, object)
RegistryKey<T>
Registers a new entry with a string ID
DynamicRegistry<Biome> biomes = MinecraftServer.getBiomeRegistry();

Biome customBiome = Biome.builder()
    .temperature(0.5f)
    .downfall(0.5f)
    .build();

RegistryKey<Biome> key = biomes.register("myplugin:custom", customBiome);
register(key, object)
RegistryKey<T>
Registers a new entry with a Key
import net.kyori.adventure.key.Key;

RegistryKey<Biome> key = biomes.register(
    Key.key("myplugin", "custom"),
    customBiome
);
Overwriting entries is unsafe and disabled by default. To enable, set the system property minestom.registry.unsafe-ops=true. Overwriting can cause desync with existing structures.

Removal

remove(key)
boolean
Removes an entry from the registry
boolean removed = biomes.remove(Key.key("myplugin:custom"));
Removal is dangerous! It remaps all subsequent IDs, which can corrupt existing worlds. Requires minestom.registry.unsafe-ops=true.

Querying

get(key)
T
Gets an entry by key
Biome plains = biomes.get(Key.key("minecraft:plains"));
getId(key)
int
Gets the protocol ID for an entry
int id = biomes.getId(biomeKey);
getKey(id)
Key
Gets the key for a protocol ID
Key key = biomes.getKey(10); // Returns key for ID 10
values()
Collection<T>
Gets all registered entries
for (Biome biome : biomes.values()) {
    // Process each biome
}

Registry Operations

Both static and dynamic registries support these operations:
get(key)
T
Gets entry by namespaced key
Block stone = blocks.get(Key.key("minecraft:stone"));
get(namespace, value)
T
Gets entry by namespace and value
Block stone = blocks.get("minecraft", "stone");
getId(key)
int
Gets protocol ID for a key
getName(id)
String
Gets namespaced name for an ID
String name = blocks.getName(1); // "minecraft:stone"
values()
Collection<T>
Gets all entries in the registry
size()
int
Gets the number of registered entries
int count = biomes.size();

Practical Examples

import net.minestom.server.MinecraftServer;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.RegistryKey;
import net.minestom.server.world.biome.Biome;
import net.kyori.adventure.key.Key;

public class CustomBiomes {
    public static final RegistryKey<Biome> VOLCANIC;
    
    static {
        DynamicRegistry<Biome> registry = MinecraftServer.getBiomeRegistry();
        
        Biome volcanic = Biome.builder()
            .temperature(2.0f)  // Very hot
            .downfall(0.0f)     // No rain
            .effects(Biome.BiomeEffects.builder()
                .fogColor(0x603020)
                .skyColor(0x800000)
                .waterColor(0xFF3300)
                .build())
            .build();
        
        VOLCANIC = registry.register("myplugin:volcanic", volcanic);
    }
    
    public static void applyToChunk(Instance instance, int chunkX, int chunkZ) {
        Chunk chunk = instance.getChunk(chunkX, chunkZ);
        if (chunk != null) {
            // Set biome for entire chunk
            chunk.setBiome(0, 0, 0, VOLCANIC);
        }
    }
}

Static Registry Reference

Available Static Registries

blocks()
Registry<Block>
All block types (stone, dirt, etc.)
material()
Registry<Material>
All item materials (diamond_sword, apple, etc.)
potionEffect()
Registry<PotionEffect>
All potion effects (speed, strength, etc.)
entityType()
Registry<EntityType>
All entity types (zombie, creeper, etc.)
fluid()
Registry<Fluid>
All fluid types (water, lava)
gameEvent()
Registry<GameEvent>
All game events for sculk sensors

Dynamic Registry Reference

Available Dynamic Registries

biome()
DynamicRegistry<Biome>
World biomes (plains, desert, etc.)
dimensionType()
DynamicRegistry<DimensionType>
Dimension configurations (overworld, nether, end)
enchantment()
DynamicRegistry<Enchantment>
Item enchantments
damageType()
DynamicRegistry<DamageType>
Damage source types
trimMaterial()
DynamicRegistry<TrimMaterial>
Armor trim materials
trimPattern()
DynamicRegistry<TrimPattern>
Armor trim patterns
bannerPattern()
DynamicRegistry<BannerPattern>
Banner patterns
paintingVariant()
DynamicRegistry<PaintingVariant>
Painting variants
jukeboxSong()
DynamicRegistry<JukeboxSong>
Music disc songs
chatType()
DynamicRegistry<ChatType>
Chat message formatting

Best Practices

Store RegistryKeys, not objects: Always store RegistryKey<T> instead of the actual object. This ensures proper serialization and network sync.
// Good
private RegistryKey<Biome> biomeKey;

// Bad
private Biome biome;
Register early: Register all custom content during server initialization, before any instances are created.
public class MyPlugin {
    public void onEnable() {
        // Register custom content first
        CustomBiomes.init();
        CustomDimensions.init();
        
        // Then create instances
        createGameWorld();
    }
}
Use namespaced keys: Always prefix custom content with your plugin/mod namespace to avoid conflicts.
// Good
registry.register("myplugin:custom_biome", biome);

// Bad (might conflict with other plugins)
registry.register("custom_biome", biome);
Avoid runtime modifications: Modifying registries after server start requires sending players to configuration phase. This interrupts gameplay and should be avoided.
Don’t enable unsafe operations: The minestom.registry.unsafe-ops flag is dangerous and can corrupt worlds. Only use it in development environments.

Build docs developers (and LLMs) love