Registry

Why is registering content so complicated?

Forge disallows you to use vanilla Registry class for registering content and requires you to register content in the RegistryEvent.Register<T> event, this is different than how you register content in fabric or vanilla.

Submitting your mod event bus in Forge to Architectury API

We will need to pass your mod event bus to Architectury API to allow Architectury API to listen to the registry events on Forge. Each mod's ModContainer handles EventBus slightly differently, and the mod event bus is inaccessible from other mods.

Now, we will expose our mod event bus to Architectury. In your forge mod constructor, do the following:

NOTE: The following tutorial only applies to mods using the javafml language provider

EventBuses.registerModEventBus(MOD_ID, FMLJavaModLoadingContext.get().getModEventBus());

Registering our content through Architectury's Registries

Via Registrar

NOTE: The following tutorial is shown in mojmap

We will create a lazy registries object, this is to prevent crashes due to static load orders.

// 1.19.4
public static final Supplier<RegistrarManager> MANAGER = Suppliers.memoize(() -> RegistrarManager.get(MOD_ID));
 
// 1.19.3 or below
public static final Supplier<Registries> REGISTRIES = Suppliers.memoize(() -> Registries.get(MOD_ID));

During your mods' initialization, you may use this REGISTRIES field to get the wrapped registries. With that, we can register our items.

// 1.19.4
Registrar<Item> items = MANAGER.get().get(Registries.ITEM);
RegistrySupplier<Item> exampleItem = items.register(new ResourceLocation(MOD_ID, "example_item"), () -> new Item(new Item.Properties()));
 
// 1.19.3 or below
Registrar<Item> items = REGISTRIES.get().get(Registry.ITEM_KEY);
RegistrySupplier<Item> exampleItem = items.register(new ResourceLocation(MOD_ID, "example_item"), () -> new Item(new Item.Properties()));

Notice that the value returned is a RegistrySupplier, this is because our content may not have been registered at this point, we might still be waiting for the registry event.

Via DeferredRegister

We will create a deferred register, we will then use this to register our entries.

// 1.19.4
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(MOD_ID, Registries.ITEM);
 
// 1.19.3 or below
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(MOD_ID, Registry.ITEM_REGISTRY);

After statically defining our deferred register, we can add entries to it, please note that the entries are not registered at this point, so we must refrain from accessing them until we actually register them.

public static final RegistrySupplier<Item> EXAMPLE_ITEM = ITEMS.register("example_item", () -> new Item(new Item.Properties()));

We can now submit our registry entries to the registry themselves, we will do this in our initialization block, please make sure that this is called only after we pass our mod event bus to architectury:

ITEMS.register();