Pretty much everything in Forge needs to be registered: blocks, items, entities, and so on. This is how I create a new registry whenever I want to have a class handle a new object. I try to avoid creating globals when I do this, but other implementations may see more uses of the static
keyword.
Checklist
- Construct the registry
- Create initialisation method
- Create accessors to registry objects
- Create and initialise it during mod construction
Construction
A basic registry needs a DeferredRegister
for the type of object you want to register, as well as a constructor for that register. The register must also be itself registered with the Mod Event Bus.
A simple registry implementation might look like this:
public class BlockRegistry { // An instance of a deferred registry we use to register items. private final DeferredRegister<Block> deferredRegister; /** * Construction * @param modEventBus The event bus to register with. */ public BlockRegistry(IEventBus modEventBus) { this.deferredRegister = DeferredRegister.create(ForgeRegistries.BLOCKS, ButterfliesMod.MOD_ID); this.deferredRegister.register(modEventBus); } }
Initialisation
Registering new objects is done in an initialise
method. A separate method is used to avoid circular dependencies on construction (e.g. Block Registries and Block Entity Registries need each other). If you are using static values and static initialisation, this method isn’t needed.
An example of a basic initialisation method is as follows:
// Butterfly Feeder private RegistryObject<Block> butterflyFeeder; /** * Register the blocks. * @param blockEntityTypeRegistry The block entity registry. * @param menuTypeRegistry The menu type registry. */ public void initialise(BlockEntityTypeRegistry blockEntityTypeRegistry, MenuTypeRegistry menuTypeRegistry) { this.butterflyFeeder = deferredRegister.register( "butterfly_feeder", () -> new ButterflyFeederBlock(blockEntityTypeRegistry, menuTypeRegistry)); }
Access
For any registered objects that need to be accessed outside of the registry, an accessor is needed. This also isn’t needed if you are using static initialisation and make all your RegistryObject
instances publicly accessible.
/** * Get the butterfly feeder block. * @return The butterfly feeder block. */ public RegistryObject<Block> getButterflyFeeder() { return butterflyFeeder; }
Mod Construction
All registries should be created and initialised in the Mod constructor. First, create all registries, then initialise them. My current registry initialisation looks like this:
/** * Constructor. */ public ButterfliesMod() { final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); final IEventBus forgeEventBus = MinecraftForge.EVENT_BUS; // Create the registries. BlockEntityTypeRegistry blockEntityTypeRegistry = new BlockEntityTypeRegistry(modEventBus); BlockRegistry blockRegistry = new BlockRegistry(modEventBus); EntityTypeRegistry entityTypeRegistry = new EntityTypeRegistry(modEventBus); ItemRegistry itemRegistry = new ItemRegistry(modEventBus); LootModifierRegistry lootModifierRegistry = new LootModifierRegistry(modEventBus); MenuTypeRegistry menuTypeRegistry = new MenuTypeRegistry(modEventBus); PoiTypeRegistry poiTypesRegistry = new PoiTypeRegistry(modEventBus); VillagerProfessionRegistry villagerProfessionRegistry = new VillagerProfessionRegistry(modEventBus); // Initialise the registries. Do this here because (e.g.) // blockEntityTypeRegistry requires blockRegistry to be created and // vice-versa. blockEntityTypeRegistry.initialise(blockRegistry, menuTypeRegistry); blockRegistry.initialise(blockEntityTypeRegistry, menuTypeRegistry); entityTypeRegistry.initialise(blockRegistry); itemRegistry.initialise(blockRegistry, entityTypeRegistry); lootModifierRegistry.initialise(itemRegistry); menuTypeRegistry.initialise(); poiTypesRegistry.initialise(blockRegistry); villagerProfessionRegistry.initialise(poiTypesRegistry); // Other initialisation stuff here. }