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#withInitial
Storage#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 Block
s.
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#translatable
now expects all arguments to be numbers, boolean, strings, or otherText
s. To pass things likeBlockPos
orIdentifier
, which were previously implicitly converted to strings, usestringifiedTranslatable
. - For those who have previously used
Codecs.TEXT
orSTRINGIFIED_TEXT
, it’s time to switch toTextCodecs.CODEC
orTextCodecs.STRINGIFIED_CODEC
. Text.Serializer
inner class was split intoSerializer
(to use as a Gson adapter) andSerialization
(contains static methods). The methods were also renamed;toJson
is nowtoJsonString
to clarify return value.Style.Serializer
is gone; it is nowStyle.Codecs
and holds the codec only.- In related news,
PacketByteBuf#readUnlimitedText
was 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_TICK
event. TickManager
can be obtained fromMinecraftServer#getTickManager
orWorld#getTickManager
(works withClientWorld
as well).- Use
shouldSkipTick
for checking if an entity should be ticked (beware, it is the inverse ofshouldTick
). - Note: You do not need to call these checks inside
Entity
/BlockEntity
tick 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#randomTick
no longer callsscheduledTick
.BlockSetType
received new fields specifying pressure plate activation conditions and button interactions with projectiles/Breezes.ColoredFallingBlock
was added, replacingGravelBlock
andSandBlock
.PowderSnowCauldronBlock
was removed;LeveledCauldronBlock
handles the logic now.TransparentBlock
was split intoTranslucentBlock
, which renders in a translucent way (like slime and ice blocks), andTransparentBlock
, which extendsTranslucentBlock
and is used by grates and glass blocks.AbstractGlassBlock
andGlassBlock
were removed.FernBlock
is renamed toShortPlantBlock
.SaplingGenerator
is now inblock
package, and individual generator classes were removed and replaced with fields.AbstractBlock#onStateReplaced
implementations for block entities were consolidated toItemScatterer#onStateReplaced
. Make sure to callsuper
AFTER callingItemScatterer
.LootableContainerBlockEntity
logics were split intoLootableInventory
.checkLootInteraction
was renamed togenerateLoot
.LootableContainerBlockEntity
still 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
copyFrom
override to copy the owner. PersistentProjectileEntity
and its subclasses now take theItemStack
in the constructor, representing the item stack form that players can pick up.getItemStack
returns the stack as-is, whileasItemStack
returns a copy (potentially reflecting the changes like potion override).SpawnReason
got two methods:isAnySpawner
(spawner & trial spawner) andisTrialSpawner
.canSpawn
methods should checkisAnySpawner
, and make the entity exempt from biome/height requirements imposed for natural spawn.
Client
PopupScreen
was 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
.CheckboxWidget
is now built using a builder.EntryListWidget
no longer takes the bottom coordinate in the constructor. It also actually became aWidget
.ClickableWidget#render
was madefinal
to prevent overrides of that method from not callingsuper.render
and preventing the tooltip from rendering. Subclasses must overriderenderWidget
instead.
Misc
CommandManager#execute
methods no longer return an integer return value. To get the return value, useServerCommandSource#withReturnValueConsumer
.RecipeProvider
methods received some changes. Some JSON builders andgenerateCookingRecipes
now require passing the constructor of recipe class, likeCampfireCookingRecipe::new
. Other builders no longer require the serializer.EntityType#HEROBRINE
was removed. (Wait, was this ever added in the first place?)