Skip to content

Registration System Module >=1.21.1 changed: 1.21.2 / 1.21.4 / 1.21.9 / 1.21.11 / 26.1

The package dev.anvilcraft.lib.v2.registrum provides a declarative registration system based on fluent builders, greatly simplifying the registration and data generation workflow for blocks, items, entities, block entities, menus, fluids, and more in Minecraft mods.

INFO

Portions of this module are based on Registrate, under the Mozilla Public License 2.0.

Architecture Overview

  1. Entry Point -- Registrum.create("modid") creates an instance and auto-registers event buses
  2. Builder -- Fluent API for chaining registration declarations (BlockBuilder, ItemBuilder, etc.)
  3. Entries -- Type-safe references obtained after registration (BlockEntry<T>, ItemEntry<T>, etc.)
  4. Data Generation -- Built-in model, loot table, recipe, tag, and language file generators

Document Index

DocumentContent
Core APIRegistrum, AbstractRegistrum core methods, event lifecycle
BuildersBuilder interface, BlockBuilder, ItemBuilder
Entity & Menu BuildersBlockEntityBuilder, EntityBuilder, MenuBuilder, FluidBuilder
Entry TypesRegistryEntry, ItemProviderEntry, BlockEntry, ItemEntry, etc.
Data GenerationGeneratorType, Provider types, 1.21.1-to-26.1 migration
ChangelogAPI changes, additions, deprecations, and removals across versions

Quick Start

java
public static final Registrum REGISTRUM = Registrum.create("mymod");

public static final BlockEntry<MyBlock> MY_BLOCK = REGISTRUM
    .object("my_block")
    .block(MyBlock::new)
        .simpleItem()           // Auto-create BlockItem
        .lang("My Block")
        .tag(BlockTags.MINEABLE_WITH_PICKAXE)
        .register();

public static final ItemEntry<MyItem> MY_ITEM = REGISTRUM
    .object("my_item")
    .item(MyItem::new)
        .tab(CreativeModeTabs.TOOLS)
        .register();

Dependency Management

Gradle (Groovy DSL)

groovy
dependencies {
    implementation "dev.anvilcraft.lib:anvillib-registrum-neoforge-26.1:2.0.0"
}

Gradle (Kotlin DSL)

kotlin
dependencies {
    implementation("dev.anvilcraft.lib:anvillib-registrum-neoforge-26.1:2.0.0")
}

Transitive Dependencies

The Registrum module internally depends on the following AnvilLib submodules:

  • anvillib-util -- Utility methods (NonNullSupplier, NonNullFunction, etc.)
  • anvillib-config -- Configuration system (used for generator configuration)

Core Concepts

object() Name State

object("name") sets a persistent state; subsequent builder calls will reuse that name until the next object() call.

java
// Recommended: explicit object() per entry
REGISTRUM.object("my_block").block(MyBlock::new).register();
REGISTRUM.object("my_item").item(MyItem::new).register();

// Also possible: reuse the same name consecutively
REGISTRUM.object("my_block")
    .block(MyBlock::new).register()  // Register block
    .object("my_block")              // Name is "my_block" (BlockEntry does not change state)
    .blockEntity(MyBE::new).register(); // Block entity with the same name

register() vs build()

  • register() -- Completes the registration chain, returns RegistryEntry (terminates the builder)
  • build() -- Equivalent to register() but returns the Parent object (allows continued chaining)
java
// register() -> returns BlockEntry
BlockEntry<MyBlock> entry = builder.register();

// build() -> returns parent, allowing continued configuration
BlockBuilder<...> parent = builder.blockEntity(MyBE::new)
    .renderer(MyRenderer::new)
    .build(); // Returns BlockBuilder; can continue .lang() .tag() etc.

Error Codes and Troubleshooting

ErrorCauseResolution
"Current name not set"Building method called on AbstractRegistrum without prior object()Call object("name") first
"Unknown registration <name> for type <registry>"get(name, type) cannot find the corresponding registration entryEnsure object(name) and builder calls precede get()
"Cannot get data provider before datagen is started"getDataProvider() called outside of the datagen phaseOnly call during GatherDataEvent
"Cannot add data generator after construction of root generator"addDataGenerator called after provider constructionRegister all data generators before GatherDataEvent
"Attempt to get non IController..." (Multiblock)Controller not registered and block does not implement IControllerCall ControllerRecord.register(controller)
"Failed to register eventListeners for mod"Registrum.create() could not find the corresponding ModContainerCheck modId spelling; ensure the mod is properly loaded
"Found unused register callbacks" (dev)Some register callbacks reference entries that were never registeredCheck that all addRegisterCallback() calls have a corresponding register()

Version Compatibility

Feature1.21.11.21.2-1.21.1126.1Notes
Core Builder APIyesyesyesBlock/Item/Entity/BlockEntity/Menu/Fluid builders are universal
GeneratorType interface--yesyesIntroduced in 1.21.2
providers/generators/ subpackage---- (1.21.4+)yesIntroduced in 1.21.4
Legacy RegistrumBlockstateProvideryesyes (through 1.21.3)--Replaced by RegistrumBlockModelGenerator in 1.21.4
nullness package locationutil.nullnessregistrum.util.nullnessutil.nullnessVaries with module.util presence
NonNullSupplier import pathv2.util.nullnessv2.registrum.util.nullnessv2.util.nullness
BIOME buildercommentedcommentedcommentedCommented out in all three versions, not enabled

Notes

  • Registration operations should be completed during the mod construction phase (in the @Mod constructor or before FMLCommonSetupEvent)
  • The name set by object(String) persists until the next call
  • skipErrors(true) only takes effect in a development environment; it is automatically ignored in production
  • Thread safety: AbstractRegistrum is not thread-safe; all registration operations should be performed on the main thread
  • Entry names are globally unique (within the modId namespace); registering a duplicate entry with the same name will overwrite the previous one

Released under the CC-BY-NC-SA 4.0 License.