It’s only been two months since we published the last article on Minecraft updates, but here we are. Minecraft 1.20.3 is to be released in the near future with some changes affecting mod makers.
As usual, we ask players to be patient, and give mod developers time to update to this new version. Given the rather short interval between updates, some authors may choose to have a rest and skip some versions; we ask everyone kindly not to pester them.
Here is a list of all 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 is about to celebrate its 5th birthday on December 10th! As we approach this milestone, we’re thrilled to share that our team is actively working on introducing exciting new features and enhancements. The following sections outline some of these advancements.
Developers should use Loom 1.4 (at the time of writing) to develop mods for Minecraft 1.20.3. Players should install the latest stable version of Fabric Loader (currently 0.14.25), or the 0.15 beta if feeling adventurous (see below).
Fabric Loader 0.15 has been released recently, which features built-in support for LlamaLad7’s MixinExtras library. This version is currently in beta. Should you discover compatibility issues with mods that already bundle MixinExtras, please file a bug report.
MixinExtras is a companion library to Mixin, providing new annotations to write your mixins in more expressive and compatible ways. It also features an easier way of specifying local captures. Due to its usefulness, MixinExtras is currently being Jar-in-Jar’d by a large amount of mods, increasing modpack sizes. With Fabric Loader bundling it now, all mods can use the library without needing to worry about distribution.
Please note that Fabric Loader 0.15 went through a number of internal changes, notably the transition from TMP to Mapping-IO and improvements to the lazy mapping loading, which reduce memory consumption. These changes do not affect most users, but mods that depend on unsupported, internal code might break with this update.
Loom 1.4 includes enhancement for decompilers, support for deprecated modules in
fabricApi.module (which allows dependencies on individual Fabric API modules), and many more bug fixes and performance improvements. Loom 1.4 requires Gradle 8.3 or later.
Loom now includes built-in support for the Vineflower decompiler. It’s a fork of Fernflower, but with drastically improved output quality compared to the original. CFR remains the default decompiler for the time being. To decompile with Vineflower, use
genSourcesWithVineflower instead of
A new DSL has been introduced to make configuring data generation with best practices easier. This DSL automatically creates a run configuration and optional source set for data generation while also excluding the cache from the built JAR:
New Fabric API changes
With the help of many contributors, Fabric API has received some new features since the last update blog post:
- Data Generation: add a method to register custom keys with priorities (ErrorCraft)
- Loot API: add
In addition to those new features, this update also contains performance improvements for
PacketType-based networking. It now skips the serialization entirely in singleplayer, and the packet is now serialized on the network thread, not the main thread. Thanks to deirn for making these improvements!
Breaking changes in 1.20.3
WoodTypeRegistry of the Object Builder API, previously deprecated, were removed. Please use the builders provided in the same API.
The following APIs in the Transfer API module, all previously deprecated, were removed.
Minecraft 1.20.3 introduces some breaking changes to major developer-facing APIs.
Mojang now uses codecs to serialize blocks - specifically, instances of a particular type of block. You might need to implement the
getCodec method in your
However, the block codecs are currently unused. This means that you can return
null or throw
That being said, it is still recommended to familiarize yourself with using codecs, to future-proof your code and prevent potential porting pains in the future.
Text also got a codec, and now is serialized using it (including when interacting with Gson). Over the network the text is now sent as an NBT.
- Important change:
Text#translatablenow expects all arguments to be numbers, boolean, strings, or other
Texts. To pass things like
Identifier, which were previously implicitly converted to strings, use
- For those who have previously used
STRINGIFIED_TEXT, it’s time to switch to
Text.Serializerinner class was split into
Serializer(to use as a Gson adapter) and
Serialization(contains static methods). The methods were also renamed;
toJsonStringto clarify return value.
Style.Serializeris gone; it is now
Style.Codecsand holds the codec only.
- In related news,
PacketByteBuf#readUnlimitedTextwas added; this reads an infinite amount of text with no size limit. Most S2C packets now use this.
/tick command from the Carpet mod arrived in the vanilla game. This change affects both the server and the client. To support this functionality in your mod:
getTickManager().shouldTick()to check if things should tick in your
TickManagercan be obtained from
shouldSkipTickfor checking if an entity should be ticked (beware, it is the inverse of
- Note: You do not need to call these checks inside
BlockEntitytick methods or events. Only call inside server/world tick events.
It is also now possible for the game to run faster or slower than 50 MSPT intentionally (as opposed to through lag). Call
TickManager#getMillisPerTick() to determine the intended MSPT.
AbstractBlock#randomTickno longer calls
BlockSetTypereceived new fields specifying pressure plate activation conditions and button interactions with projectiles/Breezes.
ColoredFallingBlockwas added, replacing
LeveledCauldronBlockhandles the logic now.
TransparentBlockwas split into
TranslucentBlock, which renders in a translucent way (like slime and ice blocks), and
TransparentBlock, which extends
TranslucentBlockand is used by grates and glass blocks.
FernBlockis renamed to
SaplingGeneratoris now in
blockpackage, and individual generator classes were removed and replaced with fields.
AbstractBlock#onStateReplacedimplementations for block entities were consolidated to
ItemScatterer#onStateReplaced. Make sure to call
LootableContainerBlockEntitylogics were split into
checkLootInteractionwas renamed to
LootableInventory, but this allows other block entities like decorated pots to share the logic.
- Boats, minecarts, and other player-constructed vehicles should now extend
VehicleEntity. This provides the wobble effect seen when hitting that entity.
- Various non-living entities (including projectiles and TNT) received
copyFromoverride to copy the owner.
PersistentProjectileEntityand its subclasses now take the
ItemStackin the constructor, representing the item stack form that players can pick up.
getItemStackreturns the stack as-is, while
asItemStackreturns a copy (potentially reflecting the changes like potion override).
SpawnReasongot two methods:
isAnySpawner(spawner & trial spawner) and
canSpawnmethods should check
isAnySpawner, and make the entity exempt from biome/height requirements imposed for natural spawn.
PopupScreenwas added. This screen, unlike other screens, renders on top of an existing screen. The popup can include a message, an image, and buttons (such as “Open Link”). To create an instance, use
CheckboxWidgetis now built using a builder.
EntryListWidgetno longer takes the bottom coordinate in the constructor. It also actually became a
finalto prevent overrides of that method from not calling
super.renderand preventing the tooltip from rendering. Subclasses must override
CommandManager#executemethods no longer return an integer return value. To get the return value, use
RecipeProvidermethods received some changes. Some JSON builders and
generateCookingRecipesnow require passing the constructor of recipe class, like
CampfireCookingRecipe::new. Other builders no longer require the serializer.
EntityType#HEROBRINEwas removed. (Wait, was this ever added in the first place?)