Fabric for Minecraft 1.21.5
A new version of Minecraft is coming soon with some changes that affect most mod makers. 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. Note that all code references are using Yarn mappings; modders using alternative mappings may need to use different names.
Fabric changes
Developers should use Loom 1.10 (at the time of writing) to develop mods for Minecraft 1.21.5. Players should install the latest stable version of Fabric Loader (currently 0.16.10).
Loom 1.10
Loom 1.10 requires Gradle 8.12, and comes with performance improvements and enhanced testing setup support. You can checkout the new Loom documentation here.
Deprecations and removals
In Content Registries, VillagerInteractionsRegistries#registerGiftLootTable
overload that takes an Identifier
was removed. This method was previously deprecated.
In Object Builder, two deprecated classes, namely VillagerProfessionBuilder
and VillagerTypeHelper
, have been removed. Use the VillagerProfession
constructor and VillagerType#create
instead. TradeOfferHelper#refreshOffers
, which had been deprecated and did nothing, was also removed.
HudRenderCallback
has been deprecated in favor of newly added HudLayerRegistrationCallback
.
Breaking changes
When a mod creates a new dynamic registry, the data pack JSON files for the registry must now be placed inside namespaced directories. For example, if the new registry is example:potato_variant
, the file for variant test:tiny
will be placed in data/test/example/potato_variant/tiny.json
.
BiomeModificationContext#addSpawn
has a new parameter, weight
. This was previously part of SpawnEntry
.
TradeOfferHelper
now takes a RegistryKey
of the profession instead of VillagerProfession
. Wandering trader trades must now be added via the builder, which was previously used for the Rebalance experiment. (The rebalanced trades are now used in all worlds.)
New Fabric API changes
With the help of many contributors, Fabric API has received some new features since the last update blog post:
- New module: Client Game Test API, which can be used to automatically test client rendering and GUI (Earthcomputer)
- New module: Fabric Tag API, which currently handles tag aliases (Juxxel)
- Convention Tags: Sync remaining
c
tags with NeoForge (TelepathicGrunt) - Convention Tags: Add
c:flowers
,c:flowers/tall
, andc:flowers/small
block and item tags (TelepathicGrunt) - Convention Tags: Add
TagKey
forc:tools/wrench
(TelepathicGrunt) - Convention Tags: Convention Drink Tags (TheDeathlyCow)
- Convention Tags: Add Pumpkin Block and Item Tags (JT122406)
- Data Generation: Add vararg helper methods for multi-tag support in
FabricTagBuilder
(Starexify) - Data Generation: Add
FabricEntityLootTableProvider
(Antikyth) - Item API: Add a method for overriding modelId in item settings (Patbox)
- Item API: Add
contains
method toFabricComponentMapBuilder
(TheDeathlyCow) - Item Group API: Change Creative Buttons Texture (matthewperiut)
- Item Group API: Use page up/down to change creative inventory pages (modmuss50)
- Model Loading API: Allow retrieving model loading plugins (PepperCode1)
- Networking API: Add
ServerPlayNetworking.reconfigure
(modmuss50) - Object Builder: Allow setting
canPotentiallyExecuteCommands
in builders (PepperCode1) - Recipe API: Add
getAllMatches
andgetAllOfType
methods toServerRecipeManager
(Patbox) - Registry Sync: Add
RegistryAttribute#OPTIONAL
that can be used to not disconnect clients lacking an entire registry; note that optional registry values are still unsupported (modmuss50) - Registry Sync: Registry aliasing (Syst3ms)
- Rendering: Add
SpecialBlockRendererRegistry
(PepperCode1) - Rendering: Add HUD Render Events (kevinthegreat1)
- Resource Loader: Implement builtin mod resource/data pack sorting (Apollo)
Tag and registry aliases
The new tag and registry alias APIs allow for mods to seemlessly migrate their tags and registry aliases to new names. Thanks to Juuxel and Syst3ms respectively for implementing these new APIs.
Registries.BLOCK.addAlias(Identifier.of("my_mod", "old"), Registries.BLOCK.get(Identifier.of("my_mod", "new")));
Registry aliases are really simple; with the code above, any access to the old ID in the registry is redirected to the new ID. This allows worlds to be upgraded to use the new ID; for example, a block with the old ID becomes the one with the new ID.
Tag aliases are defined in data packs like tags. For example, a block tag alias group for fences would be located at data/my_mod/fabric/tag_aliases/block/fences.json
with the contents:
{
"tags": [
"minecraft:fences",
"c:fences"
]
}
Client GameTest
For a long time, Fabric has had an internal client test framework that was used for testing that Fabric API was working correctly on the client. In a series of PRs, Earthcomputer has worked to expand and expose this framework to mod developers. The new experimental API has the following features:
- World creation API, for specifying options used to generate the test world.
- Screenshot API, with support for comparing against golden images.
- Input API, to simulate a user interacting with the game.
- Advanced threading setup, to make the tests more repoducible.
- Network synchronization, to ensure packets are handled consistently.
- Herobrine removal, to bring peace to the Kingdom of Tiny Potato.
For more information checkout the full documentation here.
HUD Render Events
Fabric API 0.116.0 added HudLayerRegistrationCallback
event, providing full control over the HUD rendering process. The new API assigns idenftifiers to each layer that can be used to specify where things will be rendered. The new API also allows replacing or removing existing layers. A big thanks to kevinthegreat1 and many other people for making this happen!
Minecraft changes
NBT
Significant changes to NBT handling code have been made.
NbtCompound
methods now return Optional
instead of the value. If the key is not in the compound or if the value is not of the correct type, an empty optional is now returned instead of that type’s default value.
- int value = nbt.getInt("value");
+ Optional<Integer> value = nbt.getInt("value"); // not OptionalInt
For primitives (numbers and strings), instead of checking for the existence of a key and handling a fallback, the fallback can now be passed to get
methods:
- int value;
- if (nbt.contains("value", NbtElement.NUMBER_TYPE)) {
- value = nbt.getInt("value");
- } else {
- value = 1000;
- }
+ int value = nbt.getInt("value", 1000);
Also note that NbtElement#NUMBER_TYPE
and type-aware contains
have been removed. There is no fallback method for getIntArray
, getLongArray
, and getByteArray
. (Use Optional#orElse
.)
For getCompound
and getList
methods, methods with the previous behavior (returning empty objects) are provided with OrEmpty
suffix.
- NbtCompound config = nbt.getCompound("config");
+ NbtCompound config = nbt.getCompoundOrEmpty("config");
Finally, for those who want to encode/decode codec-based values (such as Identifier
) stored in a NbtCompound
field, new methods simplify the process:
NbtCompound nbt = new NbtCompound();
nbt.put("Id", Identifier.CODEC, id);
// for reading
Optional<Identifier> id = nbt.get("Id", Identifier.CODEC);
And if there is a codec for the whole object:
NbtCompound nbt = new NbtCompound();
// have to use the RegistryOps since an item is a registry entry
nbt.copyFromCodec(ItemStack.MAP_CODEC, wrapperLookup.getOps(NbtOps.INSTANCE), stack);
// for reading
Optional<ItemStack> stack = nbt.decode(ItemStack.MAP_CODEC, wrapperLookup.getOps(NbtOps.INSTANCE));
Typed arrays (ByteArray
, IntArray
, and LongArray
) are no longer List
s. They can be converted to a list using .stream().toList()
, but this is usually not necessary. NbtList
can now contain values of differing types, but this should be a transparent change unless you work with binary data.
GameTest
In Minecraft 25w03a, Mojang totally refactored the vanilla testing framework, exposing it to datapack developers. Unfortunately, the new API is a little bit cumbersome for mod developers. Fabric API now provides its own @GameTest
annotation that functions similarly to the old one. The options in the new Fabric-provided @GameTest
annotation directly map the vanilla data-driven options, removing the need to have a JSON file for each test function. Data driven tests will still work if you wish to use the vanilla system.
Miscellaneous
DataPool
has been replaced withPool
.