A surprise update for 1.20.3 comes, with a big change to blocks! The changes are likely for the future expansion of data packs to allow custom blocks. All Block classes must(tm) now define its codec. I recommend checking the article on Fabric Modding Wiki, that should be good for most users.
A new Fabric Loader, version 0.14.23, supporting 1.20.3 versions was released. This update also comes with several changes, including support for Java 22 and duplicate loader detection that is useful in dev environment. It also changes some error messages to be more user-friendly.
Loom 1.4 was also released; this version requires Gradle 8.3. The biggest feature is the support for Vineflower (formerly known as Quiltflower) decompiler. Vineflower produces better output in certain cases, including chained methods. CFR remains the default decompiler. Other changes include fabricApi.module support for deprecated modules, disk usage improvement for multi-project mods, and additional manifest entry to check if a jar is a source file.
Fabric API 0.89.4 was released for the snapshot. The only breaking change was to the Object Builder API, whose two deprecated classes, BlockSetTypeRegistry and WoodTypeRegistry, were removed. A builder class, added in an earlier update, should be used instead.
Here is a refresher for those who have been living under rocks for 6 years: Mojang now uses DataFixerUpper "codecs" to serialize various data. This system allows the same data to be represented in NBT or JSON without writing two codes, and is designed to be fail-safe against invalid inputs.
A codec is a serialization format for a particular class: for example, a codec for TinyPotatoBlock can (de)serialize a tiny potato block instance. Each field is also serialized using codecs; for example, the field int love is serialized using Codec.INT. The wiki article mentioned above provides good example of codecs.
Back to the changes: Mojang now uses codecs to serialize blocks - specifically, instances of a particular type of block. (You cannot make an entirely new block like a cog or a piano, but you can make, for example, a new type of wood blocks.) This does not make much sense today, because block instances are created inside your code and not read from disk. This indicates however, that Mojang may be willing to make blocks data-driven to some extent.
Here are the changes for your mods. First, all blocks must now implement getCodec method. This method, however, is currently unused, so you can return null, throw UnsupportedOperationException, etc. If you do however want to future-proof the code, you need to write the codec, store it in a static final field, and return when called. For a block with no fields in the class (one whose constructor takes AbstractBlock.Settings only):
public static final MapCodec<TinyPotatoBlock> CODEC = createCodec(TinyPotatoBlock::new);
public MapCodec<TinyPotatoBlock> getCodec() {
return CODEC;
}For a block with fields, just do it like other codecs, like this (for public ColoredBlock(DyeColor color, Settings settings)):
public static final MapCodec<ColoredBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
DyeColor.CODEC.fieldOf("color").forGetter(ColoredBlock::getColor),
createSettingsCodec()
).apply(instance, ColoredBlock::new));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 anotherTexts. 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 an Gson adapter) andSerialization(contains static methods). The methods were also renamed;toJsonis nowtoJsonStringto clarify return value.Style.Serializeris gone; it is nowCodecsand holds the codec only.- Those who add a custom
TextContentorNbtDataSourcewill now need an invasive mixin. If you're one of the people who need this, contact at #api. - In a related news,
PacketByteBuf#readUnlimitedTextwas added; this reads an infinite amount of text with no size limit. Most S2C packets now use this.
AbstractBlock#randomTickno longer callsscheduledTick.BlockSetTypereceivedcanButtonBeActivatedByArrowsandpressurePlateSensitivityfields.pressurePlateSensitivityis specified usingActivationRuleenum.ColoredFallingBlockwas added, replacingGravelBlockandSandBlock.PowderSnowCauldronBlockwas removed;LeveledCauldronBlockhandles the logic now.SaplingGeneratoris now inblockpackage, and individual generator classes were removed and replaced with fields.
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.ClientPlayNetworkHandler#clearWorldwas split intoclearWorld(for disconnection) andunloadWorld(for temporary disconnection like reconfiguration).clearWorldcallsunloadWorldinside.
LivingEntity#getMaxRelativeHeadRotation, which... returns the max head rotation relative to the body in degrees, which by default is 50. Fun fact: human necks' horizontal range of motion is up to 90 degrees.IdListis now reference (identity)-keyed. Many otherRegistryKey-keyed maps were converted to reference maps as well.StringIdentifiablecan now be used with non-enums, viacreateBasicCodec. This does not supportbyIdmethod.Util#lastIdentityIndexGetterwas added; this is the identity comparison version oflastIndexGetter.Uuids#STRICT_CODECwas added. UnlikeCODEC, undashed UUIDs are not supported with this codec.Codecs#BASIC_OBJECTandRuntimeOpswere added. This allows serialization of basic objects - primitives, strings, lists, and maps - without writing a codec yourself. Since the returned result has raw types, however, this should not be used in most cases.- GameTest users can now use
expectItem(Item)anddontExpectItem(Item)methods inTestContext. They detect item entities within the entire bounding box of the test structure. EntityType#HEROBRINEwas removed. (Wait, was this ever added in the first place?)MathHelper#rotateAround, which is useful if you are a linear algebra nerd and know what you are doing.
Thank you for this gist! As someone starting out with 1.20.4, trying to scrounge up documentation on the required
getCodec()was tough.