Fabric for Minecraft 26.3
Minecraft 26.3 - the Wilderness Bound game drop - releases on September 15th, with some changes that will affect most mod developers.
As always, we ask all players to be patient, and give mod developers time to update to this new version. We kindly ask everyone not to pester them. We also recommend all players make backups of their worlds.
Here is a list of several major modder-facing changes in this version, using the names provided by the unobfuscated game.
Fabric changes
Developers should use Loom 1.17 and Gradle 9.6.0 (at the time of writing) to develop mods for Minecraft 26.3. Players should install the latest stable version of Fabric Loader (currently 0.19.5).
API removals
Various APIs have been removed due to vanilla refactors. All of the functionality provided by these APIs is now available through other means, either in vanilla or in new APIs.
The following APIs have been removed:
CompostingChanceRegistryandFuelRegistry: see the ‘Fuel and compostable components’ section under Minecraft changes.FabricPotionBrewingBuilder: see the ‘Brewing recipes’ section under Minecraft changes.StrippableBlockRegistry,TillableBlockRegistry, andFlattenableBlockRegistry: see the ‘Block transformers’ section under Minecraft changes.
Fluid APIs
The fluid behaviour API is no longer considered experimental, and has received additional methods for controlling isInFluid, onFluidEntered, and onFluidExited.
FluidVariantAttributes#enableColoredVanillaFluidNames has been removed and replaced by FluidVariantAttributes#getColoredName, allowing individual mods to provide coloured fluid names in their GUIs without enabling it for an entire modpack.
A fluid flow API has been introduced, adding a callback triggered by the following actions:
- A flowable fluid tries to spread to a new block
- A liquid block is placed
- A liquid block has its neighbor updated
As an example, this can be used for modded cobblestone generators, like this one that allows a modded fluid flowing above blue ice to create Ice.
FluidFlowCallback.EVENT.register((fluid, level, position) -> {
// Check we are the test fluid
if (!fluid.is(MODDED_FLUID_KEY)) return true;
// Check we are above blue ice
if (!level.getBlockState(position.below()).is(Blocks.BLUE_ICE)) return true;
level.setBlockAndUpdate(position, Blocks.ICE.defaultBlockState());
level.playSound(null, position, SoundEvents.GLASS_PLACE, SoundSource.BLOCKS, 1, 1);
return false;
});
TooltipFlag extensions
Both Fabric and NeoForge have added a method to TooltipFlag, shouldDisplayAllInformation. This method can be used to allow tooltip information, especially tooltips gated by keybinds, to be indexed by external mods like recipe viewers.
Enchantment power provider API
Fabric’s block extensions now allow modded blocks to specify how much enchantment power they provide by overriding Block#getProvidedEnchantmentPower.
Minecraft changes
26.3’s technical changes are focused primarily on rendering (as always), new item components, world generation, and registries. We have only listed a few of the major non-rendering changes not covered in the previous section here. For a more comprehensive list of changes, please see NeoForged’s upcoming porting “primer”.
Fuel and compostable components
Compostables, furnace fuel, and brewing fuel are now determined via item components; DataComponents.COMPOSTABLE, DataComponents.COOKING_FUEL, and DataComponents.BREWING_FUEL respectively.
These components can either be applied at item registration for your own items, or via DefaultItemComponentEvents for items from vanilla or other mods.
As a result, Fabric API’s CompostingChanceRegistry and FuelRegistry have been removed.
/// before
FuelRegistry.INSTANCE.add(MODDED_ITEM, 1);
CompostableRegistry.INSTANCE.add(SomeOtherMod.OTHER_MODDED_ITEM, 1);
// after, at item registration
MODDED_ITEM = new Item(new Item.Properties()
.component(DataComponents.COOKING_FUEL,
new CookingFuel(new ResolvableInt.Constant(1), ResolvableFloat.fromKey(ContextFloatProviders.COOKING_DEFAULT_SPEED_MULTIPLIER))));
// after, using the event
DefaultItemComponentEvents.MODIFY.register(modifyContext -> {
modifyContext.modify(SomeOtherMod.OTHER_MODDED_ITEM, builder -> {
builder.set(DataComponents.COMPOSTABLE,
new Compostable(new ResolvableInt.Constant(1*100)))
});
});
Note that these components can make use of data driven number providers to determine their values. See the ‘Number providers’ section below for more information on those.
Brewing recipes
Brewing recipes are now data driven like other recipe types in the game, registered through json files inside data packs in the recipe folder.
As a result, FabricPotionBrewingBuilder, its BUILD event, and its methods have been removed. Addition, modification, and removal of brewing recipes should now be done like any other recipe type in the game. You can use data generation to generate the JSON files with code.
See the brewing section of the Minecraft wiki’s recipe article for more information.
Block transformers
Block transformers are a new vanilla data type, responsible for handling the transformation of blocks when right clicked with an item. In vanilla, this includes hoes tilling dirt into farmland, shovels flattening dirt into paths, and axes both stripping logs and scraping wax and oxidation.
To create new transformers, register them through JSON files inside data packs, in the block_transformer folder. You can use data generation to generate the JSON files with code.
A block transformer is then added to an item with the DataComponents.BLOCK_TRANSFORMER item component. This component can either be applied at item registration for your own items, or via DefaultItemComponentEvents for items from vanilla or other mods.
As a result, Fabric API’s StrippableBlockRegistry, TillableBlockRegistry, and FlattenableBlockRegistry have been removed, and their functionality has been moved into the new BlockTransformerHelper, which has various helper methods for adding on to vanilla block transformers.
// before
TillableBlockRegistry.register(MODDED_DIRT, HoeItem::onlyIfAirAbove, HoeItem.changeIntoState(MODDED_FARMLAND.defaultBlockState()));
// after
BlockTransformerHelper.registerTilling(MODDED_DIRT, MODDED_FARMLAND);
A new event also exists for more advanced modification of block transformers, similar to the system used by the enchantment events.
BlockTransformerEvents.MODIFY.register(
(key, transforms, source, registries) -> {
if (key == SomeOtherMod.CHISEL_TRANSFORMER) {
// add a new transform to turn nether bricks into cracked nether bricks, with a nether bricks hit sound
transforms.add(
BlockTransformer.BlockTransformData.builder(
BlockPredicate.matchesBlocks(Blocks.NETHER_BRICKS),
Blocks.CRACKED_NETHER_BRICKS
).sound(Holder.direct(SoundEvents.NETHER_BRICKS_HIT)).build()
);
}
}
);
Note that these APIs should only be used for modifying transformers from outside sources - vanilla or other mods. Creating your own new transformers should be done via JSON files in your mods’ data pack.
See the block transformer definition article on the Minecraft wiki for more information.
Dynamic registries
Minecraft 26.3 has made some significant changes to reloadable registries. They now include recipes and advancements and use the same registry loading path as other dynamic registries. Mods can now register their own reloadable registry as well.
DynamicRegistries.registerReloadable(RELOADABLE_REGISTRY_KEY, ReloadableRegistryObject.CODEC);
Configured features
Configured features have been moved to the new worldgen/feature folder, and Feature has been combined with FeatureConfiguration into a new Feature interface.
Codecs of new feature types are registered to BuiltInRegistries.FEATURE_TYPE, rather than BuiltInRegistries.FEATURE.
In data, the config object has been removed and configuration is part of the feature directly. Various placement modifiers were also renamed.
You can use data generation to generate the JSON files with code. Examples of how to data generate these new features will be available on the Fabric Docs shortly after release.
Surface material rules
Surface rules have been renamed to material rules, and can now be registered instead of always being inlined. They are registered through JSON files inside data packs, in the worldgen/material_rule folder. You can use data generation to generate the JSON files with code.
This allows for modification of material rules without overwriting the entire Overworld dimension, though external libraries may still be desired to safely inject into vanilla material rules.
Most places they were previously inlined can now optionally be a reference to a registered material rule ID.
Material conditions
Material conditions can now be registered instead of always being inlined. They are registered through json files inside data packs, in the worldgen/material_condition folder. You can use data generation to generate the JSON files with code.
This allows for modification of material conditions without overwriting the entire material rule, though external libraries may still be desired to safely inject into vanilla material conditions.
Most places they were previously inlined can now optionally be a reference to a registered material condition ID.
Number providers
Number providers have been split into float providers and integer providers, and many additional types have been added, mostly pertaining to mathematical functions.
Furthermore, these providers can now be registered instead of always being inlined. They are registered through json files inside data packs, in the context_float_provider and context_int_provider folders. You can use data generation to generate the JSON files with code.
This allows for modification of number providers without overwriting the data they’re used in entirely, though external libraries may still be desired to safely inject into that vanilla data.
Number providers are used by vanilla in various item components (specifically the new ones pertaining to composting and fuel), as well as loot tables, predicates, villager trades, and the new /compute command. Most places they were previously inlined can now optionally be a reference to a registered number provider ID.
See the number provider article on the Minecraft wiki for more informaton.
Block state providers
Block state providers can now be registered instead of always being inlined. They are registered through JSON files inside data packs, in the worldgen/block_state_provider folder. You can use data generation to generate the JSON files with code.
This allows for modification of block state providers without overwriting the data they’re used in entirely, though external libraries may still be desired to safely inject into that vanilla data.
Many types have also been slightly renamed to remove redundant suffixes.
Block state providers are used by vanilla in block transformers and feature generation. Most places they were previously inlined can now optionally be a reference to a registered block state provider ID.
See the block state provider article on the Minecraft wiki for more information.
Block codecs no more
Previously, all Block classes defined a Codec. These Codecs went largely unused, seemingly being part of Mojang’s future plans for data driving blocks, but have now been removed entirely, along with the block_type registry they were registered to.
SDL
The GLFW library used for window and keybind management has been removed in favour of SDL. SDL has many benefits including a broader API than GLFW, so modders interacting with input outside the game may wish to check its documentation.
This will primarily affect developers using input constants from GLFW instead of the vanilla InputConstants class. Some of the constants used (including all mouse buttons) were also changed, so do not attempt to hardcode your inputs to avoid using InputConstants.
Developers creating custom text-input widgets should generally notify TextInputManager when their text-input focus changes, otherwise the SDL backend will become out of sync and character input will entirely break. An example of this is below, and more info can be found in this GitHub issue.
import com.mojang.blaze3d.platform.TextInputManager;
public class MyTextInputWidget {
// ...
public void setFocused(boolean isFocused) {
// ...
// Manually update the text input focus.
Minecraft.getInstance().textInputManager().onTextInputFocusChange(isFocused);
// If your element implements `GuiEventListener`, you can instead use this method in `Minecraft` which also handles the preedit event state
Minecraft.getInstance().onTextInputFocusChange(this, isFocused)
}
}
Fabric