Content, such as Blocks and Items, is registered using helpers you can access through the BalmRegistrars instance that is passed to your initializer. Balm provides various convenient helper methods for registering standard content, as well as the ability to register into any other registry using the generic registrar(...) method.
public class Waystones {
public static DeferredBlock waystoneBlock;
public static void initialize(BalmRegistrars registrars) {
registrars.blocks(registrar -> {
waystoneBlock = blocks.register("waystone", WaystoneBlock::new, it -> it.sound(SoundType.STONE).strength(5f, 2000f)).withItem(WaystoneBlockItem::new).asDeferredBlock();
});
}
}
As your mod grows, it often makes sense to split content registrations into their own classes depending on their type.
public class ModBlocks {
public static void initialize(BalmBlockRegistrar blocks) {
blocks.register(registrar -> {
waystoneBlock = blocks.register("waystone", WaystoneBlock::new,
it -> it.sound(SoundType.STONE)
.strength(5f, 2000f)
).withItem(WaystoneBlockItem::new).asDeferredBlock();
});
}
}
public class Waystones {
public static void initialize(BalmRegistrars registrars) {
registrars.blocks(ModBlocks::initialize);
}
}
In a multi-loader context, registrations are not necessarily instant across all loaders.
While Fabric registers content the moment you make the call, NeoForge and Forge defer registrations until a later time.
That's why anything you register with Balm will generally either provide you with a Holder, or something like DeferredBlock or DeferredItem rather than the Block or Item directly.
Many Minecraft methods accept Holders (or Balm's DeferredBlock and DeferredItem classes) just fine, but if you need to, you can access the underlying values using Holder.value() or e.g. DeferredBlock.asBlock().
DeferredBlock also comes with a useful defaultBlockState() method (since that is what you most commonly need a Block field for), and both DeferredBlock and DeferredItem have a createStack(int count) method to quickly get a new ItemStack of them.
itemStack.getItem() == ModItems.warpStone, as they will always be false when using DeferredItem. Use itemStack.is(ModItems.warpStone) instead, or consider using an Item Tag where it makes sense.The most common registries are covered by specialized Balm...Registrar classes which not only provide useful helpers for registering things in a neat and streamlined manner, but may also take care of additional steps in the background that are needed to make your content function. Therefore, if Balm provides a specialized registrar for the registry you need, you should use it to avoid issues.
For registries that are not covered by Balm, you can use the custom registrar method instead:
public class ModSounds {
public static Holder<SoundEvent> fridgeOpen;
public static void initialize(BalmRegistrar.Scoped<SoundEvent> sounds) {
fridgeOpen = sounds.register("fridge_open", SoundEvent::createVariableRangeEvent);
}
}
public class CookingForBlockheads {
public static void initialize(BalmRegistrars registrars) {
registrars.registrar(Registries.SOUND_EVENT, ModSounds::initialize);
}
}