Again, you CANNOT access the blocks until after the event has fired. They simply don't exist.
Use the ID, or the RegistryObject itself, it is an instance of Supplier<T>.
I use the following 3 methods to register my blocks:
/**
* Register a block and a default ItemBlock with the Item group set to my Item group.
*/
private static <T extends Block> RegistryObject<T> register(String name, Supplier<? extends T> block) {
return register(name, block, (b) -> () -> new BlockItem(b.get(), new Item.Properties().group(AAItems.ITEM_GROUP)));
}
/**
* Register a block and an Item using a custom Item supplier.
* @param itemCreator type is (block) -> Supplier<Item>. (block passed in so you could use the same function to define multiple block items).
*/
private static <T extends Block> RegistryObject<T> register(String name, Supplier<? extends T> block, Function<RegistryObject<T>, Supplier<? extends Item>> itemCreator) {
RegistryObject<T> ret = registerBlockOnly(name, block);
ITEMS.register(name, itemCreator.apply(ret));
return ret;
}
/**
* Register a block with no item (could be used for door/bed halves etc.).
*/
private static <T extends Block> RegistryObject<T> registerBlockOnly(String name, Supplier<? extends T> sup) {
return BLOCKS.register(name, sup);
}
The reason why you have to pass in suppliers to the DeferredRegister#register methods is so that they can call them in the registry events, i.e. at the correct time.
Note that using the block/item objects .get() in suppliers ONLY WORKS FOR GETTING BLOCKS AND ITEMS. This is because those 2 registry events are fired in that order, before any others, and until the event has fired, the object doesn't exist, so cannot be used in other events. (The order of other registries is random, so it might work sometimes and not others.) If you need to access other registry objects, you need to use a supplier (as in pass the actual RegistryObject into the constructor) and get the object when it is needed.