Skip to content

Registration

MehVahdJukaar edited this page Jul 25, 2026 · 1 revision

Registration

RegHelper registers anything, on any loader, with the same call. No DeferredRegister, no per loader boilerplate.

It covers every vanilla registry (blocks, items, entities, block entities, menus, sounds, effects, enchantments, particles, recipes, loot, worldgen, POIs, brain memories and activities, creative tabs...), plus the things that aren't really registries: creative tab contents, loot table injects, attributes, spawn placements, commands, compostables, burn times, flammability.

It also registers new registries and new datapack registries, and data attachments (one API over NeoForge attachments and Fabric's component storage) for sticking data on entities, block entities, chunks or levels.

Getting Started

On Forge and NeoForge, hand Moonlight your mod event bus first:

RegHelper.startRegisteringFor(modEventBus);

Then just declare static fields. They register when the class loads:

public static final Supplier<FlowerBlock> LILAC = RegHelper.registerBlockWithItem(
        MyMod.res("lilac"),
        () -> new FlowerBlock(MobEffects.HARM, 1, BlockBehaviour.Properties.of()));

// anything else: same call, plus the registry key
public static final Supplier<GameEvent> CUSTOM_EVENT = RegHelper.register(
        MyMod.res("custom_event"), () -> new GameEvent(2), Registries.GAME_EVENT);

You get back a RegSupplier, which is both a Supplier and a Holder.

Things that are an event rather than a registry take a callback on init:

RegHelper.addItemsToTabsRegistration(event ->
        event.addAfter(CreativeModeTabs.BUILDING_BLOCKS,
                stack -> stack.is(ItemTags.FLOWERS), LILAC.get()));

ItemToTabEvent can add, insert before or after a matched item, and remove, in any tab including other mods'.

Example: RegHelperExample

Shortcuts worth knowing

registerBlockWithItem does the block and its BlockItem in one go.

registerFullBlockSet(id, properties) registers block, slab, stairs and wall at once (also registerBaseBlockSet and registerReducedBlockSet). Unrelated to the Block Set API, which is about wood and leaves types.

registerInBatch(registry, event -> ...) when you have a pile of entries for one registry.

Data attachments

public static final IAttachmentType<MyData, Entity> MY_DATA = RegHelper.registerDataAttachment(
        MyMod.res("my_data"),
        () -> RegHelper.AttachmentBuilder.create(MyData::new)
                .persistent(MyData.CODEC)     // saved to disk
                .copyOnDeath()                // survives respawn
                .syncWith(MyData.STREAM_CODEC),
        Entity.class);

Lazy references

For datapack registry entries, and for blocks from mods that might not be installed:

DynamicHolder<DamageType> IN_FIRE = DynamicHolder.of(id, Registries.DAMAGE_TYPE);
OptionalHolder<Block> DEPLOYER = OptionalHolder.of(ResourceLocation.parse("create:deployer"), Registries.BLOCK);

Both implement Holder and Supplier, so they drop into anything expecting either.

Clone this wiki locally