Fabric for Minecraft 1.20.3 & 1.20.4
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 changes
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).
Loader 0.15
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
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 genSources.
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:
fabricApi {
configureDataGeneration()
}
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
LootTableEvents.LOADED(LLytho)
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
BlockSetTypeRegistry and 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.
ContainerItemContext#withInitialStorage#simulateInsert,simulateExtract,exactView
Minecraft changes
Minecraft 1.20.3 introduces some breaking changes to major developer-facing APIs.
Block codecs
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 Blocks.
However, the block codecs are currently unused. This means that you can return null or throw UnsupportedOperationException in getCodec method.
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
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 otherTexts. To pass things likeBlockPosorIdentifier, which were previously implicitly converted to strings, usestringifiedTranslatable. - For those who have previously used
Codecs.TEXTorSTRINGIFIED_TEXT, it’s time to switch toTextCodecs.CODECorTextCodecs.STRINGIFIED_CODEC. Text.Serializerinner class was split intoSerializer(to use as a Gson adapter) andSerialization(contains static methods). The methods were also renamed;toJsonis nowtoJsonStringto clarify return value.Style.Serializeris gone; it is nowStyle.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.
Ticks
The /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:
- Use
getTickManager().shouldTick()to check if things should tick in yourSTART_WORLD_TICK/END_WORLD_TICK/START_SERVER_TICK/END_SERVER_TICKevent. TickManagercan be obtained fromMinecraftServer#getTickManagerorWorld#getTickManager(works withClientWorldas well).- Use
shouldSkipTickfor checking if an entity should be ticked (beware, it is the inverse ofshouldTick). - Note: You do not need to call these checks inside
Entity/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.
Blocks
AbstractBlock#randomTickno longer callsscheduledTick.BlockSetTypereceived new fields specifying pressure plate activation conditions and button interactions with projectiles/Breezes.ColoredFallingBlockwas added, replacingGravelBlockandSandBlock.PowderSnowCauldronBlockwas removed;LeveledCauldronBlockhandles the logic now.TransparentBlockwas split intoTranslucentBlock, which renders in a translucent way (like slime and ice blocks), andTransparentBlock, which extendsTranslucentBlockand is used by grates and glass blocks.AbstractGlassBlockandGlassBlockwere removed.FernBlockis renamed toShortPlantBlock.SaplingGeneratoris now inblockpackage, and individual generator classes were removed and replaced with fields.AbstractBlock#onStateReplacedimplementations for block entities were consolidated toItemScatterer#onStateReplaced. Make sure to callsuperAFTER callingItemScatterer.LootableContainerBlockEntitylogics were split intoLootableInventory.checkLootInteractionwas renamed togenerateLoot.LootableContainerBlockEntitystill implementsLootableInventory, but this allows other block entities like decorated pots to share the logic.
Entities
- 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 theItemStackin the constructor, representing the item stack form that players can pick up.getItemStackreturns the stack as-is, whileasItemStackreturns a copy (potentially reflecting the changes like potion override).SpawnReasongot two methods:isAnySpawner(spawner & trial spawner) andisTrialSpawner.canSpawnmethods should checkisAnySpawner, and make the entity exempt from biome/height requirements imposed for natural spawn.
Client
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, useBuilder.CheckboxWidgetis now built using a builder.EntryListWidgetno longer takes the bottom coordinate in the constructor. It also actually became aWidget.ClickableWidget#renderwas madefinalto prevent overrides of that method from not callingsuper.renderand preventing the tooltip from rendering. Subclasses must overriderenderWidgetinstead.
Misc
CommandManager#executemethods no longer return an integer return value. To get the return value, useServerCommandSource#withReturnValueConsumer.RecipeProvidermethods received some changes. Some JSON builders andgenerateCookingRecipesnow require passing the constructor of recipe class, likeCampfireCookingRecipe::new. Other builders no longer require the serializer.EntityType#HEROBRINEwas removed. (Wait, was this ever added in the first place?)
Fabric