In Minecraft 1.21.5, Balm has removed some long-standing deprecations, and refactored the way configs and capabilities are handled.
/balm export icons is not yet functionalThe command has not yet been updated to Minecraft's rendering changes.
BalmModule and BalmClientModule, an alternative way to initialize your modsModules are a slightly cleaner way of interacting with Balm, where instead of accessing Balm services through the Balm helper class in your initializer, you instead override the appropriate register* method in your module and have it called by Balm at the appropriate time.
Read through the Modules documentation to learn more.
BalmConfigSchema for Declarative ConfigsConfigs have been refactored for a much cleaner and more stable code-base, while also adding the ability to define a configuration programmatically instead of only statically through annotations.
The previous annotation-based approach is still present and will remain, however some packages and annotations have been renamed for clarity.
Balm now also supports different config types, although only common and client are universally supported across all mod loaders.
BalmConfig and Declarative Configs have been backported to 1.20.1, 1.21.1 and 1.21.4.SyncConfigMessage has been removedBalm now automatically takes care of syncing mod's configs through its own packet. Mods no longer need to register a packet of their own.
BalmConfigSchema as an alternative way to define configsConfigs are now no longer directly tied to a given data class. Instead, their structure is defined in a schema, very similar to how config specs are built in Forge and NeoForge.
However, the annotation-based approach remains and will continue to function. Schemas will be auto-generated for annotation-based configs so both can use the same code in the back.
Read through the Mod Configurations documentation for more information.
Annotations such as @Config, @Comment and @Synced are now available under the package net.blay09.mods.balm.api.config.reflection.
ExpectedType has been renamed to NestedTypeThe new name makes it more clear that the annotation is meant to be used for collections / generics.
BalmConfigData has been removedThe interface served no purpose beyond slightly better type-safety.
Since mods generally only access their config classes in two places (registerConfig and getActiveConfig) where errors are easy to notice, the interface has been removed for simplicity.
BalmCapabilities replaces BalmProvidersThe previous BalmProviders implementation was heavily biased towards Forge's approach to capabilities and had several shortcomings that resulted in a lot of mod-loader-specific boilerplate. It has been removed in favor the new BalmCapabilities service.
With this new service, it is now possible to universally register capabilities, capability providers, and fallback providers through Balm.
Read through the Capabilities documentation for more information.
BalmCapabilities service has been backported to 1.20.1, 1.21.1 and 1.21.4.BalmModels.loadModel now returns a BlockStateModelBlockStateModel can be used in the same manner that BakedModel was, with the difference that you must use collectParts(RandomSource) to pass them into the tesselateBlock method.
BalmRenderers and BalmScreens registration methods now require a ResourceLocation identifierWhile this identifier is not technically used by Minecraft or mod loaders, Balm needs it to attribute your objects to the appropriate mod.
As a side-effect, this should also be more future-proof since more and more things are moving to registries or at least being identifiable.
FluidTank and EnergyStorage are now an interfaceAn interface was added as to not limit the respective Balm capabilities to only Balm's default implementation.
In return, the default implementation has been renamed to DefaultFluidTank and DefaultEnergyStorage.
If you are querying for a FLUID_TANK or ENERGY_STORAGE capability, you should handle the interface under the same name as previously.
If you are defining your own fluid tank or energy storage, you should use DefaultFluidTank and DefaultEnergyStorage or a custom implementation.
isConnectedToServer has been renamed to isConnectedThis method is available through Balm.getProxy() and can be used before sending packets to ensure they are only sent if the player is actually ingame.
This was changed to avoid confusion on what this method does. Unlike the previous name may have suggested, it is not the equivalent of an isMultiplayer() method.
isConnected checks if the client is connected to any server, be it the integrated singleplayer server, a LAN server, or a dedicated server.
Balm.registerConfig may not load your config immediately anymoreOn Forge and NeoForge, common and client configs are no longer immediately available. Accessing the config in your initializer will result in a crash. You can instead use the new ConfigLoadedEvent to act only once the config is available.
However, that may be too late if you need access to the configuration for e.g. setting up item components. There is no good universal solution to this as of now.
ReloadableResourceManagerAdding reload listeners to the ReloadableResourceManager directly is no longer supported, as NeoForge had made the list immutable in favor of their registration event.
Balm now provides an addResourceReloadListener method that uses the proper channels to register the listener on each mod loader.
Functionally, this method behaves the same as registering a reload listener directly used to.
BalmBlocksblockProperties() has been removedBlock Properties now require an identifier to be set, and mod-loader specific BlockBehaviour.Properties no longer exist, making this method obsolete. Instead, there is now a static blockProperties(ResourceLocation) utility method you can use.
registerBlock(Supplier, ResourceLocation) has been removedUse registerBlock(Function, ResourceLocation) instead, which gives you access to the identifier you passed in (since you'll need it to construct your block properties).
registerBlockItem(Supplier, ResourceLocation) and registerBlockItem(Supplier, ResourceLocation, ResourceLocation) has been removedUse registerBlockItem(Function, ResourceLocation) or registerBlockItem(Function, ResourceLocation, ResourceLocation) instead, which gives you access to the identifier you passed in (since you'll need it to construct your item properties).
register(Supplier, Supplier, ResourceLocation) and register(Supplier, Supplier, ResourceLocation, ResourceLocation) has been removedUse register(Function, BiFunction, ResourceLocation) or register(Function, BiFunction, ResourceLocation, ResourceLocation) instead, which gives you access to the identifier you passed in, since you'll need it to construct your block and item properties.
Additionally, the BiFunction for your block item also gets the constructed block passed in, simplifying registration further.
BalmItemsitemProperties() has been removedItem Properties now require an identifier to be set, and mod-loader specific Item.Properties no longer exist, making this method obsolete. Instead, there is now a static itemProperties(ResourceLocation) utility method you can use.
registerItem(Supplier, ResourceLocation) and registerItem(Supplier, ResourceLocation, ResourceLocation) has been removedUse registerItem(Function, ResourceLocation) or registerItem(Function, ResourceLocation, ResourceLocation) instead, which gives you access to the identifier you passed in (since you'll need it to construct your item properties).
BalmNetworkingopenGui has been removed in favor of openMenuThe new method name more accurately describes what the method does and is functionally identical.
registerClientboundPacket that takes Consumer and Function for encoding and decoding has been removedMinecraft is migrating its network protocol to use StreamCodecs, which are a composable way of declaring the structure of the data that gets sent and received.
You can still use StreamCodec.of(encoder, decoder) to create a StreamCodec with imperative code, although it is recommended to migrate to using StreamCodec.composite(...), as this declarative approach is less error-prone.
BalmHooksgetBurnTime has been removedYou can instead use level.fuelValues().burnDuration(itemStack).
isShield has been removedYou can instead check for the DataComponents.BLOCKS_ATTACKS data components.
isRepairable has been removedYou can instead check for the DataComponents.REPAIRABLE or DataComponents.REPAIR_COST data components.
getBlockReachDistance has been removedYou can instead query the Attributes.BLOCK_INTERACTION_RANGE attribute.
BalmRegistriesgetKey, getItemKeys and getItem/... has been removedThese methods are all available through the respective registry in BuiltinRegistries instead.
getItemTag has been removedYou can instead easily create a TagKey<Item> yourself:
TagKey<Item> yourTag = TagKey.create(Registries.ITEM, yourResourceLocation);
BalmKeyMappingsKeyConflictContext and KeyModifier have been removedKuma is the preferred solution for dealing with special key mappings, which allows defining defaults as well as fallbacks should key modifiers not be supported by the mod loader.
Kuma is already embedded in Balm, so you can safely depend on it without needing to jar-in-jar it.
isActive* methods have been removedSince Balm no longer provides the functionality for key conflict contexts and modifiers, you can now just use the existing methods from the KeyMapping to check for its state.
If you use Kuma, you can access the state on the ManagedKeyMapping, or use the event handlers when registering your keys to define your logic.
ignoreConflicts(KeyMapping) and related methods have been removedThese methods were added to allow configuring key modifiers through dummy key mappings, but they were never really functional due to Minecraft's limitation of only supporting an input to be bound to a single key. In prior Balm versions, these methods already no-op'ed.
KeyConflictContext, KeyModifier and KeyModifiers have been removedIf you were using these classes, you should instead use Kuma or define your own.
BalmRecipesregisterRecipeType that takes both RecipeType and RecipeSerializer has been removedUse registerRecipeType and registerRecipeSerializer individually instead.
BalmTexturesThis class was already empty and has not been needed for a while, since custom textures can be added to atlases through resource packs.
ExtractionAwareContainerThis interface was highly incompatible with other mods as the extraction checks were only performed when Balm's own ContainerUtils were used.
Instead, you should implement Vanilla's Container.canTakeItem or WorldlyContainer.canTakeItemThroughFace in your container.