Skip to main content

Minecraft 1.21.5

info

These migration notes cover only the changes made to Balm APIs.

For Minecraft and mod-loader specific migrations, check out their respective release announcements or primers.

Overview

In Minecraft 1.21.5, Balm has removed some long-standing deprecations, and refactored the way configs and capabilities are handled.

⚠️ Known Issues

Extra Models are missing on Fabric

Fabric has not yet re-added the API for loading extra models. Balm defaults to the missing model so your code can at least run without crashing.

/balm export icons is not yet functional

The command has not yet been updated to Minecraft's rendering changes.

Notable Additions and Changes

BalmModule and BalmClientModule, an alternative way to initialize your mods

Modules 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 Configs

Configs 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.

Annotation-based Configs

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.

tip

The changes to BalmConfig and Declarative Configs have been backported to 1.20.1, 1.21.1 and 1.21.4.

SyncConfigMessage has been removed

Balm now automatically takes care of syncing mod's configs through its own packet. Mods no longer need to register a packet of their own.

Added BalmConfigSchema as an alternative way to define configs

Configs 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.

Renamed some packages for annotation-based configs

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 NestedType

The new name makes it more clear that the annotation is meant to be used for collections / generics.

BalmConfigData has been removed

The 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 BalmProviders

The 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.

tip

The new BalmCapabilities service has been backported to 1.20.1, 1.21.1 and 1.21.4.

Minor Changes

BalmModels.loadModel now returns a BlockStateModel

BlockStateModel 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.

warning

Extra Models are not currently supported on Fabric. They will always return the missing model.

BalmRenderers and BalmScreens registration methods now require a ResourceLocation identifier

While 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 interface

An 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 isConnected

This 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.

Caveats

Balm.registerConfig may not load your config immediately anymore

On 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.

note

This was the case all the way back to 1.20.1, but it was not as noticeable because Balm would simply return the default values for a configuration.

Newer versions of Balm will crash if the config is accessed too early.

Reload Listeners can no longer be added directly to ReloadableResourceManager

Adding 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.

Removals

Removals in BalmBlocks

blockProperties() has been removed

Block 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 removed

Use 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 removed

Use 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 removed

Use 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.

Removals in BalmItems

itemProperties() has been removed

Item 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 removed

Use 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).

Removals in BalmNetworking

openGui has been removed in favor of openMenu

The 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 removed

Minecraft 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.

Removals in BalmHooks

getBurnTime has been removed

You can instead use level.fuelValues().burnDuration(itemStack).

isShield has been removed

You can instead check for the DataComponents.BLOCKS_ATTACKS data components.

isRepairable has been removed

You can instead check for the DataComponents.REPAIRABLE or DataComponents.REPAIR_COST data components.

getBlockReachDistance has been removed

You can instead query the Attributes.BLOCK_INTERACTION_RANGE attribute.

Removals in BalmRegistries

getKey, getItemKeys and getItem/... has been removed

These methods are all available through the respective registry in BuiltinRegistries instead.

getItemTag has been removed

You can instead easily create a TagKey<Item> yourself:

TagKey<Item> yourTag = TagKey.create(Registries.ITEM, yourResourceLocation);

Removals in BalmKeyMappings

Registration methods taking KeyConflictContext and KeyModifier have been removed

Kuma 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.

Modifier- and Context-aware isActive* methods have been removed

Since 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.

These 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 removed

If you were using these classes, you should instead use Kuma or define your own.

Removals in BalmRecipes

registerRecipeType that takes both RecipeType and RecipeSerializer has been removed

Use registerRecipeType and registerRecipeSerializer individually instead.

Removal of BalmTextures

This class was already empty and has not been needed for a while, since custom textures can be added to atlases through resource packs.

Removal of ExtractionAwareContainer

This 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.