Registry Builder
Overview
Section titled “Overview”The RegistryBuilder is the core API for registering content from common code that works on both Fabric and NeoForge. It provides a simple, unified interface for registering items, blocks, block entities, sounds, creative tabs, and more with automatic mod ID prefixing.
Creating a Registry
Section titled “Creating a Registry”Instead of creating a RegistryBuilder directly, extend the specific registry classes for better organization and type safety. Matthiesen Lib provides abstract registry classes for different content types:
AbstractItemRegistry- For registering itemsAbstractBlockRegistry- For registering blocksAbstractBlockEntityRegistry- For registering block entity typesAbstractMenuTypeRegistry- For registering menu/container typesAbstractCommandRegistry- For registering commandsAbstractSoundRegistry- For registering sound eventsAbstractCreativeModeTabRegistry- For registering creative mode tabsAbstractDataComponentTypeRegistry- For registering custom data component typesAbstractCriteriaTriggerRegistry- For registering advancement criterion triggersAbstractStatsRegistry- For registering custom statisticsAbstractEntityEffectRegistry- For registering enchantment entity effects
Example: Item Registry
Section titled “Example: Item Registry”package dev.matthiesen.common.mymod.registry;
import dev.matthiesen.common.matthiesen_lib.registry.AbstractItemRegistry;import net.minecraft.world.item.Item;import java.util.function.Supplier;
public class ItemRegistry extends AbstractItemRegistry { private static final ItemRegistry INSTANCE = new ItemRegistry();
protected ItemRegistry() { super("mymod"); // Your mod ID }
public static void init() { // Called to trigger static initialization }
// Register your items public static final Supplier<Item> MY_ITEM;
static { MY_ITEM = INSTANCE.register("my_item", () -> new Item(new Item.Properties())); }}The mod ID is automatically prefixed to all registered content, so you only need to provide the item/block name.
Registering Content
Section titled “Registering Content”Register items by extending AbstractItemRegistry:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractItemRegistry;import net.minecraft.world.item.Item;import java.util.function.Supplier;
public class ItemRegistry extends AbstractItemRegistry { private static final ItemRegistry INSTANCE = new ItemRegistry();
protected ItemRegistry() { super("mymod"); }
public static void init() {}
public static final Supplier<Item> EXAMPLE_ITEM; public static final Supplier<Item> CUSTOM_ITEM;
static { EXAMPLE_ITEM = INSTANCE.register("example_item", () -> new Item(new Item.Properties())); CUSTOM_ITEM = INSTANCE.register("custom_item", CustomItem::new); }}In your mod initializer, call ItemRegistry.init() to trigger registration.
Blocks
Section titled “Blocks”Register blocks by extending AbstractBlockRegistry:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractBlockRegistry;import net.minecraft.world.level.block.Block;import net.minecraft.world.level.block.state.BlockBehaviour;import java.util.function.Supplier;
public class BlockRegistry extends AbstractBlockRegistry { private static final BlockRegistry INSTANCE = new BlockRegistry();
protected BlockRegistry() { super("mymod"); }
public static void init() {}
public static final Supplier<Block> EXAMPLE_BLOCK;
static { EXAMPLE_BLOCK = INSTANCE.register("example_block", () -> new Block(BlockBehaviour.Properties.of() .strength(3.0f, 3.0f) ) ); }}Commands
Section titled “Commands”Register commands using AbstractCommandRegistry:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractCommandRegistry;
public class CommandRegistry extends AbstractCommandRegistry { private static final CommandRegistry INSTANCE = new CommandRegistry();
protected CommandRegistry() { super(); }
public static void init() {}
static { INSTANCE.register(new MyCommand()); }}See the Commands page for details on creating commands.
Menu Types
Section titled “Menu Types”Register menu types for container screens using AbstractMenuTypeRegistry:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractMenuTypeRegistry;import net.minecraft.world.inventory.MenuType;import java.util.function.Supplier;
public class MenuTypesRegistry extends AbstractMenuTypeRegistry { private static final MenuTypesRegistry INSTANCE = new MenuTypesRegistry();
protected MenuTypesRegistry() { super("mymod"); }
public static void init() {}
public static Supplier<MenuType<CustomMenu>> CUSTOM_MENU; public static Supplier<MenuType<AnotherMenu>> ANOTHER_MENU;
static { CUSTOM_MENU = INSTANCE.register("custom_menu", CustomMenuFactory::create); ANOTHER_MENU = INSTANCE.register("another_menu", AnotherMenuFactory::create); }}Sound Events
Section titled “Sound Events”Register custom sounds using AbstractSoundRegistry:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractSoundRegistry;import net.minecraft.sounds.SoundEvent;import net.minecraft.core.registries.BuiltInRegistries;import java.util.function.Supplier;
public class SoundRegistry extends AbstractSoundRegistry { private static final SoundRegistry INSTANCE = new SoundRegistry();
protected SoundRegistry() { super("mymod"); }
public static void init() {}
public static Supplier<SoundEvent> MY_SOUND;
static { MY_SOUND = INSTANCE.register("my_sound", () -> SoundEvent.createVariableRangeEvent( ResourceLocation.fromNamespaceAndPath("mymod", "my_sound") ) ); }}Creative Mode Tabs
Section titled “Creative Mode Tabs”Register custom creative mode tabs using AbstractCreativeModeTabRegistry:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractCreativeModeTabRegistry;import dev.matthiesen.common.matthiesen_lib.MatthiesenLib;import net.minecraft.world.item.CreativeModeTab;import java.util.function.Supplier;
public class CreativeTabRegistry extends AbstractCreativeModeTabRegistry { private static final CreativeTabRegistry INSTANCE = new CreativeTabRegistry();
protected CreativeTabRegistry() { super("mymod"); }
public static void init() {}
public static Supplier<CreativeModeTab> MY_TAB;
static { MY_TAB = INSTANCE.register("my_tab", () -> new MatthiesenLib.RegistryBuilder("mymod").newCreativeTabBuilder() .title(Component.translatable("itemGroup.mymod.my_tab")) .icon(() -> new ItemStack(ItemRegistry.MY_ITEM.get())) .displayItems((parameters, output) -> { output.accept(ItemRegistry.MY_ITEM.get()); output.accept(ItemRegistry.ANOTHER_ITEM.get()); }) .build() ); }}Block Entities
Section titled “Block Entities”Register block entity types using AbstractBlockEntityRegistry:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractBlockEntityRegistry;import net.minecraft.world.level.block.entity.BlockEntityType;import java.util.function.Supplier;
public class BlockEntityRegistry extends AbstractBlockEntityRegistry { private static final BlockEntityRegistry INSTANCE = new BlockEntityRegistry();
protected BlockEntityRegistry() { super("mymod"); }
public static void init() {}
public static Supplier<BlockEntityType<MyBlockEntity>> MY_BLOCK_ENTITY;
static { MY_BLOCK_ENTITY = INSTANCE.register("my_block_entity", () -> BlockEntityType.Builder.of( MyBlockEntity::new, BlockRegistry.MY_BLOCK.get() ).build(null) ); }}Data Component Types
Section titled “Data Component Types”Register custom data component types for item NBT data:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractDataComponentTypeRegistry;import net.minecraft.core.component.DataComponentType;import java.util.function.Supplier;
public class DataComponentRegistry extends AbstractDataComponentTypeRegistry { private static final DataComponentRegistry INSTANCE = new DataComponentRegistry();
protected DataComponentRegistry() { super("mymod"); }
public static void init() {}
public static Supplier<DataComponentType<Integer>> MY_COMPONENT;
static { MY_COMPONENT = INSTANCE.register("my_component", () -> DataComponentType.<Integer>builder() .persistent(Codec.INT) .networkSynchronized(ByteBufCodecs.VAR_INT) .build() ); }}Criterion Triggers
Section titled “Criterion Triggers”Register custom advancement criterion triggers:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractCriteriaTriggerRegistry;import net.minecraft.advancements.CriterionTrigger;import java.util.function.Supplier;
public class CriteriaTriggerRegistry extends AbstractCriteriaTriggerRegistry { private static final CriteriaTriggerRegistry INSTANCE = new CriteriaTriggerRegistry();
protected CriteriaTriggerRegistry() { super("mymod"); }
public static void init() {}
public static Supplier<CriterionTrigger<MyTrigger.TriggerInstance>> MY_TRIGGER;
static { MY_TRIGGER = INSTANCE.register("my_trigger", () -> new MyTrigger()); }}Custom Statistics
Section titled “Custom Statistics”Register custom statistics for player tracking:
import dev.matthiesen.common.matthiesen_lib.registry.AbstractStatsRegistry;import net.minecraft.resources.ResourceLocation;import java.util.function.Supplier;
public class StatsRegistry extends AbstractStatsRegistry { private static final StatsRegistry INSTANCE = new StatsRegistry();
protected StatsRegistry() { super("mymod"); }
public static void init() {}
public static Supplier<ResourceLocation> MY_STAT;
static { MY_STAT = INSTANCE.register("my_stat", () -> ResourceLocation.fromNamespaceAndPath("mymod", "my_stat") ); }}Best Practices
Section titled “Best Practices”Use Suppliers
Section titled “Use Suppliers”Always use Supplier<T> for your registered content. This ensures lazy initialization and prevents null pointer exceptions:
// Goodpublic static final Supplier<Item> MY_ITEM;
static { MY_ITEM = INSTANCE.register("my_item", () -> new Item(new Item.Properties()));}
// Avoidpublic static final Item MY_ITEM = INSTANCE.register(...).get(); // Don't call .get() during static initNaming Conventions
Section titled “Naming Conventions”- Use
snake_casefor registry names:"gui_item","example_block" - This automatically becomes
mymod:gui_itemin-game - Use descriptive names that clearly indicate what the item/block is
Organization
Section titled “Organization”Organize your registrations by type in dedicated registry classes:
public class ItemRegistry extends AbstractItemRegistry { // All item registrations}
public class BlockRegistry extends AbstractBlockRegistry { // All block registrations}
public class MenuTypesRegistry extends AbstractMenuTypeRegistry { // All menu type registrations}Initialization
Section titled “Initialization”Make sure to call init() on all your registry classes during mod initialization to trigger static initialization:
public class MyMod { public void initialize() { ItemRegistry.init(); BlockRegistry.init(); MenuTypesRegistry.init(); CommandRegistry.init(); PermissionRegistry.init(); }}Available Registry Classes
Section titled “Available Registry Classes”| Registry Class | Purpose | Register Method |
|---|---|---|
AbstractItemRegistry | Register items | register(name, supplier) |
AbstractBlockRegistry | Register blocks | register(name, supplier) |
AbstractBlockEntityRegistry | Register block entity types | register(name, supplier) |
AbstractMenuTypeRegistry | Register menu types | register(name, supplier) |
AbstractSoundRegistry | Register sound events | register(name, supplier) |
AbstractCreativeModeTabRegistry | Register creative mode tabs | register(name, supplier) |
AbstractDataComponentTypeRegistry | Register data component types | register(name, supplier) |
AbstractCriteriaTriggerRegistry | Register criterion triggers | register(name, supplier) |
AbstractStatsRegistry | Register custom statistics | register(name, supplier) |
AbstractEntityEffectRegistry | Register enchantment entity effects | register(name, supplier) |
AbstractCommandRegistry | Register commands | register(command) |