<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.0">Jekyll</generator><link href="https://fabricmc.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://fabricmc.net/" rel="alternate" type="text/html" /><updated>2026-03-07T08:47:30+00:00</updated><id>https://fabricmc.net/feed.xml</id><title type="html">Fabric</title><subtitle>The home of the Fabric mod development toolchain.</subtitle><entry><title type="html">Fabric for Minecraft 1.21.11</title><link href="https://fabricmc.net/2025/12/05/12111.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.21.11" /><published>2025-12-05T00:00:00+00:00</published><updated>2025-12-05T00:00:00+00:00</updated><id>https://fabricmc.net/2025/12/05/12111</id><content type="html" xml:base="https://fabricmc.net/2025/12/05/12111.html">&lt;p&gt;A new version of Minecraft is coming soon with some changes that affect most mod makers. As always, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version&lt;/strong&gt;. We kindly ask everyone not to pester them. &lt;strong&gt;We also recommend all players make backups of their worlds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As you may be aware, we expect &lt;a href=&quot;https://www.minecraft.net/en-us/article/removing-obfuscation-in-java-edition&quot;&gt;1.21.11 to be the last version of Minecraft that is obfuscated&lt;/a&gt;. The next snapshot will be the first version of Minecraft that will &lt;strong&gt;not&lt;/strong&gt; be obfuscated.&lt;/p&gt;

&lt;p&gt;Mojang have also recently announced that they will be &lt;a href=&quot;https://www.minecraft.net/en-us/article/minecraft-new-version-numbering-system&quot;&gt;changing how the game is versioned&lt;/a&gt;. The next version will be known as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;26.1&lt;/code&gt;. This new versioning nicely lines up with the unobfuscation process, as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.21.11&lt;/code&gt; will be the last obfuscated version.&lt;/p&gt;

&lt;p&gt;Here is a list of several major modder-facing changes in this version. Note that all code references are using Mojang’s mappings; modders using alternative mappings, including our previously default Yarn mappings, may need to use different names.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;

&lt;p&gt;Developers should use Loom 1.14 (at the time of writing) to develop mods for Minecraft 1.21.11. Players should install the latest stable version of Fabric Loader (currently 0.18.1).&lt;/p&gt;

&lt;h3 id=&quot;world-render-events&quot;&gt;World Render Events&lt;/h3&gt;

&lt;p&gt;The World Render Events were recently reintroduced into Fabric API for 1.21.10. Mods that required them to port can now do so. The new World Render Events are intended to match with recent changes to Minecraft itself, focusing on separating extraction from rendering.&lt;/p&gt;

&lt;p&gt;Rendering in the world has been documented on the &lt;a href=&quot;https://docs.fabricmc.net/develop/rendering/world&quot;&gt;Fabric Docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;packet-splitter-and-recipe-sync-api&quot;&gt;Packet Splitter and Recipe Sync API&lt;/h3&gt;

&lt;p&gt;Fabric now offers an opt-in packet splitter, allowing for mods that have packets that would exceed the size of a vanilla one to easily be split between multiple packets.&lt;/p&gt;

&lt;p&gt;Implementing the packet splitter is simple - use the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerLarge&lt;/code&gt; method when registering your packet.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;PayloadTypeRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;playS2C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerLarge&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;YourPayload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;YourPayload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DATA_SIZE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Thanks to this API, Fabric also now offers a way for mods to synchronize recipes from the server to the client, comparable to the behavior prior to 1.21.1. This API has already been adopted by recipe viewers like JEI, but means that recipe viewers are required on the server.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;RecipeSynchronization&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;synchronizeRecipeSerializer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;YourRecipeSerializers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;RECIPE_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;

&lt;p&gt;The following section details a few of the more notable changes to Minecraft that affected the Fabric API.&lt;/p&gt;

&lt;h3 id=&quot;game-rules&quot;&gt;Game rules&lt;/h3&gt;

&lt;p&gt;Game rules were refactored to use the Registry system; Mods should now use the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameRuleBuilder&lt;/code&gt; API to create and register custom game rules.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GameRule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EXAMPLE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GameRuleBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forBoolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;buildAndRegister&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fromNamespaceAndPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fabric&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above snippet creates and registers a new boolean game rule with the default value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameRuleBuilder&lt;/code&gt; API provides the following factory methods &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forInteger&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forDouble&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forBoolean&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forEnum&lt;/code&gt; to create game rules of different types. The builder also allows for additional configuration such as setting the category, required features and command result suppiler.&lt;/p&gt;

&lt;p&gt;The new version of Fabric API also includes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameRuleEvents&lt;/code&gt; class that provides an event for listening to game rule changes. Mods can use this event to perform actions when a game rule is changed.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;GameRuleEvents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;changeCallback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GameRules&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FIRE_DAMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;// Your code here&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;environment-attributes&quot;&gt;Environment Attributes&lt;/h3&gt;

&lt;p&gt;The Biome Modification API has been updated to support the new Environment Attributes system. Mods can now modify environment attributes such as temperature, humidity, and altitude for biomes using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiomeModificationContext#AttributesContext&lt;/code&gt; class. You can access the attributes context by using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAttributes()&lt;/code&gt; method on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiomeModificationContext&lt;/code&gt; object.&lt;/p&gt;

&lt;h2 id=&quot;an-update-on-unobfuscation&quot;&gt;An update on unobfuscation&lt;/h2&gt;

&lt;p&gt;Alongside updating to each 1.21.11 snapshot, Fabric has been working towards &lt;a href=&quot;https://fabricmc.net/2025/10/31/obfuscation.html&quot;&gt;making this transition as smooth as possible&lt;/a&gt;. Currently, Mojang has been releasing experimental unobfuscated versions of Minecraft alongside the obfuscated ones, allowing us to test and prepare for the transition.&lt;/p&gt;

&lt;p&gt;With that in mind, this is a good time to begin &lt;a href=&quot;https://docs.fabricmc.net/develop/migrating-mappings/&quot;&gt;remapping your mods to the official Mojang Mappings&lt;/a&gt;, as Yarn will not be available for the version of Minecraft after 1.21.11. The differences between Mojang mappings and the unobfuscated game do not affect compilation, so switching to Mojang mappings now will allow for an easier transition when porting to future snapshots. There is no immediate rush to do this, as we anticipate the first unobfuscated stable release will be a few months into 2026.&lt;/p&gt;

&lt;p&gt;The unobfuscation process has raised many questions. We’ve answered some of the more common ones here, but please reach out in the Fabric Discord if you have any specific questions.&lt;/p&gt;

&lt;h3 id=&quot;is-12111-obfuscated-or-not&quot;&gt;Is 1.21.11 obfuscated or not?&lt;/h3&gt;

&lt;p&gt;Yes, 1.21.11 is still obfuscated. The next version of Minecraft after 1.21.11, &lt;a href=&quot;https://www.minecraft.net/en-us/article/minecraft-new-version-numbering-system&quot;&gt;26.1&lt;/a&gt;, will be the first unobfuscated version.&lt;/p&gt;

&lt;h3 id=&quot;are-yarn-and-intermediary-still-going-to-be-updated-past-12111&quot;&gt;Are Yarn and Intermediary still going to be updated past 1.21.11?&lt;/h3&gt;

&lt;p&gt;No, the plan is to stop updating Yarn and Intermediary after 1.21.11. Modders should begin migrating to Mojang Mappings as soon as possible.&lt;/p&gt;

&lt;h3 id=&quot;what-if-i-want-to-use-custom-mappings&quot;&gt;What if I want to use custom mappings?&lt;/h3&gt;

&lt;p&gt;You can still opt to use custom mappings, we plan to continue to maintain support for remapping in Loom. However, please be aware that using custom mappings may require additional work to ensure compatibility with the unobfuscated game and other mods.&lt;/p&gt;

&lt;h3 id=&quot;will-my-simple-mod-still-work-on-261-without-changes&quot;&gt;Will my simple mod still work on 26.1 without changes?&lt;/h3&gt;

&lt;p&gt;No, all mods that interact with Minecraft code will need to be recompiled to be compatible with the unobfuscated version of Minecraft.&lt;/p&gt;

&lt;h3 id=&quot;my-mod-is-using-yarn-mappings-how-do-i-migrate&quot;&gt;My mod is using Yarn mappings, how do I migrate?&lt;/h3&gt;

&lt;p&gt;We’ve put together an updated article on the &lt;a href=&quot;https://docs.fabricmc.net/develop/migrating-mappings/&quot;&gt;Fabric Docs site&lt;/a&gt; that covers the process of migrating mappings. In short - Loom should be able to handle most mods, and is now able to remap mixins, and third-party tools like Ravel can be used for more complicated projects (like Fabric API itself) or mods using Kotlin.&lt;/p&gt;

&lt;h3 id=&quot;what-is-intermediary&quot;&gt;What is Intermediary?&lt;/h3&gt;

&lt;p&gt;Intermediary is a project we used to create stable names for Minecraft code across versions. This worked by giving each unique class, method, and field an ID that would remain the same across versions. This is not the same as the obfuscated names that Mojang uses as these change completely with each version. Intermediary allowed mods compiled against one version of Minecraft to continue working on future versions, as long as the underlying code did not change significantly.&lt;/p&gt;

&lt;p&gt;Once the game is unobfuscated, there will no longer be a need for Intermediary, as method names should no longer change drastically between releases.&lt;/p&gt;

&lt;h3 id=&quot;what-changes-if-i-am-already-using-mojangs-mappings&quot;&gt;What changes if I am already using Mojang’s mappings?&lt;/h3&gt;

&lt;p&gt;If you are already using Mojang Mappings, the transition to the unobfuscated version of Minecraft should be relatively smooth. You may need to adjust any code that relies on synthetic methods or fields (search for ‘method_’ or ‘field_’ in your project.). Any usage of Fabric Loader’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MappingResolver&lt;/code&gt; can likely be removed. You will need to migrate your build script to the new Loom variant that does not support remapping. We will provide more detailed guidance as we get closer to the release of the unobfuscated version of Minecraft.&lt;/p&gt;

&lt;h3 id=&quot;will-fabric-be-quicker-to-update&quot;&gt;Will Fabric be quicker to update?&lt;/h3&gt;

&lt;p&gt;Yes! With the removal of obfuscation, we no longer need to manually update Yarn and Intermediary for each new version of Minecraft. This means that Fabric Loader and Loom will be able to use new versions as soon as they are released by Mojang. Fabric API will still require updates to accommodate changes to Minecraft itself. For stable releases where Fabric API has already been updated to a release candidate, we expect there will be no delay in fully supporting the new version of Minecraft.&lt;/p&gt;

&lt;h3 id=&quot;so-minecraft-is-open-source-now&quot;&gt;So Minecraft is open source now?&lt;/h3&gt;

&lt;p&gt;No, nothing really changes in that regard. Mojang previously released their obfuscation mappings publicly allowing anyone to see the deobfuscated names of classes, methods, and fields if they remaped the code. This change simply means that the code itself that players use will no longer be obfuscated, making it easier for modders to work with without needing an extra step. The Minecraft &lt;a href=&quot;https://www.minecraft.net/en-us/eula&quot;&gt;EULA&lt;/a&gt; has also not changed.&lt;/p&gt;

&lt;h3 id=&quot;how-much-easier-will-modding-be&quot;&gt;How much easier will modding be?&lt;/h3&gt;

&lt;p&gt;A little bit, as local variable names will now be available in the code, which helps to make debugging and understanding Minecraft’s code easier. Crash reports will no longer require translation. However, developing mods will still require a good understanding of Java, Minecraft’s systems and the modding APIs being used. This will not allow mods to do anything they weren’t able to do before.&lt;/p&gt;</content><author><name></name></author><summary type="html">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.</summary></entry><entry><title type="html">Removing Obfuscation from Fabric</title><link href="https://fabricmc.net/2025/10/31/obfuscation.html" rel="alternate" type="text/html" title="Removing Obfuscation from Fabric" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://fabricmc.net/2025/10/31/obfuscation</id><content type="html" xml:base="https://fabricmc.net/2025/10/31/obfuscation.html">&lt;p&gt;Mojang recently published &lt;a href=&quot;https://www.minecraft.net/en-us/article/removing-obfuscation-in-java-edition&quot;&gt;a blog post&lt;/a&gt; announcing that they will be removing obfuscation from Minecraft: Java Edition starting with the first snapshot after the &lt;em&gt;Mounts of Mayhem&lt;/em&gt; launch later this year. There will also be supplementary “experimental” releases starting with next Tuesday’s snapshot to allow us time to prepare and migrate.&lt;/p&gt;

&lt;p&gt;This is a major change that will affect the entire modding community. This blog post will attempt to give a rundown of how the Fabric toolchain will be affected, and what this means for Fabric mod developers.&lt;/p&gt;

&lt;h2 id=&quot;what-is-obfuscation&quot;&gt;What is obfuscation?&lt;/h2&gt;
&lt;p&gt;Obfuscation is a practice by which the names of classes, methods, fields, etc. in the code of the game are hidden by changing them into meaningless sequences of letters that change every version. So, as an example, the class for Creepers may have been changed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Creeper&lt;/code&gt; to something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This has been a practice used for practically the entire time Minecraft has existed, and has meant that people who want to mod the game needed to figure out what each part of the code did, and use tools to apply readable names back to the code.&lt;/p&gt;

&lt;h3 id=&quot;what-has-been-done-about-obfuscation-before&quot;&gt;What has been done about obfuscation before?&lt;/h3&gt;
&lt;p&gt;In the Fabric world, we have had projects called Intermediary and Yarn.
Intermediary would take the obfuscated names and give them stable numbers - so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brc&lt;/code&gt; might become &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class_1548&lt;/code&gt;.
Yarn would then apply readable names to those numbers - so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class_1548&lt;/code&gt; might become &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CreeperEntity&lt;/code&gt;.
These Yarn names were created and determined by our community by analysing the code. (If you’ve seen things in the code named with the Intermediary numbers - those are things we didn’t get around to naming in Yarn!)&lt;/p&gt;

&lt;p&gt;Since 2019, while the code of the game itself has still used the scrambled letters, Mojang has released their own official set of readable names, colloquially known as ‘Mojmap’, which are the names they themselves use when developing the game.
This set of names was different from Yarn, and many developers embraced them, though some continued using Yarn names out of preference.
Fabric has supported the option to use either set of names.&lt;/p&gt;

&lt;h3 id=&quot;what-does-it-mean-that-obfuscation-is-being-removed&quot;&gt;What does it mean that obfuscation is being removed?&lt;/h3&gt;
&lt;p&gt;Now, the names in the actual code of the game will match those that Mojang has been releasing since 2019. What’s more, for the first time, mod developers will now be able to see official names for method parameters and local variables, which were previously missing from those names.&lt;/p&gt;

&lt;p&gt;However, as the Fabric toolchain has been built around the need to apply our own names, this means a lot of work will have to go into supporting this change.&lt;/p&gt;

&lt;h2 id=&quot;what-is-fabric-going-to-do&quot;&gt;What is Fabric going to do?&lt;/h2&gt;
&lt;p&gt;We have plans in place to update our toolchain, but there’s a lot to do, and this may take some time.&lt;/p&gt;

&lt;h3 id=&quot;the-future-of-fabric-api&quot;&gt;The future of Fabric API&lt;/h3&gt;
&lt;p&gt;Fabric API will &lt;strong&gt;not&lt;/strong&gt; undergo major rewrites as a result of this, and all of your favourite APIs will stay on course.
However, the naming of the APIs and their associated methods and javadoc will change to accurately reflect the official Mojang names.&lt;/p&gt;

&lt;p&gt;The first stage of this will be to migrate Fabric API to use the official Mojang names in a non API-breaking way. This will happen fairly quickly as it can be done with no impact to modders and players.&lt;/p&gt;

&lt;p&gt;When the new fully deobfuscated version is released, we will rename Fabric’s own API functions to match those of the official names.&lt;/p&gt;

&lt;h3 id=&quot;loom&quot;&gt;Loom&lt;/h3&gt;
&lt;p&gt;Development of a new Loom version has begun. The initial goal is to provide a solution for mod developers to begin using the new experimental releases for testing. This will likely take the form of Loom 1.13.&lt;/p&gt;

&lt;p&gt;In the long run we may look into making a totally new version of Loom that is more modular. Loom 2.0 may provide a slim version that contains no support for remapping. This will likely take some time, and is still in the design phase so please be patient.&lt;/p&gt;

&lt;p&gt;Support for modding older game versions with the latest Loom is a very high priority and something that we wish to continue to provide as we have done previously. We also understand that not everyone wishes to use the new official names, we hope to provide a remapping solution for those advanced users who wish to use their own names.&lt;/p&gt;

&lt;h3 id=&quot;the-future-of-yarn&quot;&gt;The future of Yarn&lt;/h3&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/rip_yarn.png&quot; alt=&quot;Example Image&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;The Fabric community as a whole thanks all 261 Yarn contributors for their 9 years, 2 months, and 17 days of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt; glory. Your contributions have been and continue to be greatly appreciated.&lt;/p&gt;

&lt;p&gt;Unfortunately, given the current circumstances we can’t see a way to justify maintaining Yarn in its current state.&lt;/p&gt;

&lt;p&gt;Yarn for existing Minecraft versions will continue to welcome contributions.&lt;/p&gt;

&lt;p&gt;If you are a mod developer using Yarn mappings, you will likely need to migrate to Mojang’s names. See the ‘For mod developers’ section below.&lt;/p&gt;

&lt;h2 id=&quot;what-do-i-need-to-do&quot;&gt;What do I need to do?&lt;/h2&gt;
&lt;h3 id=&quot;for-players&quot;&gt;For players&lt;/h3&gt;
&lt;p&gt;Very little! This is largely only going to affect developers. We aim to keep supporting all existing launchers.&lt;/p&gt;

&lt;p&gt;In good news, this also means once all this is sorted, updates for some things like Fabric API will likely be quicker in the future, and crash logs might be slightly easier to read. Rejoice!&lt;/p&gt;

&lt;p&gt;And as always, we ask all players to be patient, and give mod developers time to update. We kindly ask everyone not to pester them. We also recommend all players make backups of their worlds before updating to any new version.&lt;/p&gt;

&lt;h3 id=&quot;for-mod-developers&quot;&gt;For mod developers&lt;/h3&gt;

&lt;p&gt;This is going to be a large change, especially for those that are using Yarn. There is no expectation to update your mods right away, but you may wish to prepare. Nothing will change until after the &lt;em&gt;Mounts of Mayhem&lt;/em&gt; (1.21.11) drop.&lt;/p&gt;

&lt;p&gt;We recommend that all new mods should be created using the official Mojang mappings, this will provide an easier upgrade path in the future.&lt;/p&gt;

&lt;p&gt;If you have a mod using Yarn, don’t worry! Loom has existing automated tooling that will help you to rename your code. We are actively looking at ways to improve this tooling and plan to provide some resources in the future to help you.&lt;/p&gt;

&lt;p&gt;Once you have upgraded, you will benefit from a much simpler and faster toolchain, improved logs/crash reports and new debugging options.&lt;/p&gt;

&lt;h2 id=&quot;tldr-what-will-affect-you&quot;&gt;TL;DR: What will affect you&lt;/h2&gt;

&lt;h3 id=&quot;players&quot;&gt;Players&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Be patient while mods update.&lt;/li&gt;
  &lt;li&gt;Crash logs may be slightly easier to read.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;modders&quot;&gt;Modders&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Don’t worry! There is no rush.&lt;/li&gt;
  &lt;li&gt;Most Yarn users will need to migrate to the official names.&lt;/li&gt;
  &lt;li&gt;Your build script will require some changes.&lt;/li&gt;
  &lt;li&gt;Production crash logs may be slightly easier to debug.&lt;/li&gt;
  &lt;li&gt;Intermediary will no longer exist; the game will use Mojang’s names at runtime.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">Mojang recently published a blog post announcing that they will be removing obfuscation from Minecraft: Java Edition starting with the first snapshot after the Mounts of Mayhem launch later this year. There will also be supplementary “experimental” releases starting with next Tuesday’s snapshot to allow us time to prepare and migrate.</summary></entry><entry><title type="html">Fabric for Minecraft 1.21.9 &amp;amp; 1.21.10</title><link href="https://fabricmc.net/2025/09/23/1219.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.21.9 &amp;amp; 1.21.10" /><published>2025-09-23T00:00:00+00:00</published><updated>2025-09-23T00:00:00+00:00</updated><id>https://fabricmc.net/2025/09/23/1219</id><content type="html" xml:base="https://fabricmc.net/2025/09/23/1219.html">&lt;p&gt;A new version of Minecraft is coming soon with some changes that affect most mod makers. As always, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version.&lt;/strong&gt; We kindly ask everyone not to pester them. &lt;strong&gt;We also recommend all players make backups of their worlds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;
&lt;p&gt;Developers should use Loom 1.11 (at the time of writing) to develop mods for Minecraft 1.21.9.
Players should install the latest stable version of Fabric Loader (currently 0.17.2).&lt;/p&gt;

&lt;h3 id=&quot;yarn-mappings&quot;&gt;Yarn Mappings&lt;/h3&gt;
&lt;p&gt;In this update, several mapping name changes were forced by changes in the vanilla class hierarchy. While a full diff may be found &lt;a href=&quot;https://github.com/FabricMC/yarn/compare/d9167974e1fc83c980cf3be9fb567b1ab67d1153..6f9f183d2908d05e67a89aa3558caf9fee207dc0&quot;&gt;here&lt;/a&gt;, there is one major change affecting almost all mods: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Entity#getWorld&lt;/code&gt; was renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Entity#getEntityWorld&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;world-render-events&quot;&gt;World Render Events&lt;/h3&gt;
&lt;p&gt;The current event suite for rendering in the world has been removed. A suitable replacement is planned asap, but not ready yet. In the meantime, please use mixins to implement what your mod needs.&lt;/p&gt;

&lt;h3 id=&quot;resource-loader-api-v1&quot;&gt;Resource Loader API v1&lt;/h3&gt;

&lt;p&gt;A major rework of the resource loader API is present in the 1.21.9 version of Fabric API. This will make current functionality easier to acomplish, as well as opening doors for features like runtime resource generation in the future.&lt;/p&gt;

&lt;p&gt;The first part of this rework has just landed with the focus being on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceReloader&lt;/code&gt;.
Historically this API based itself on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IdentifiableResourceReloadListener&lt;/code&gt; interface which allowed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceReloader&lt;/code&gt; to both be identifiable and specify dependencies.
However this API had limits, which prevented to run before another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceReloader&lt;/code&gt; or was difficult to use in multiloader environments.
This has been fixed with this new iteration of the API.&lt;/p&gt;

&lt;p&gt;From now on, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceReloader&lt;/code&gt; do not need to implement a Fabric-provided interface, instead they can be registered with an identifier directly:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new CustomResourceReloader())
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ ResourceLoader.get(ResourceType.SERVER_DATA).registerReloader(Identifier.of(&quot;modid&quot;, &quot;custom_resource_reloader&quot;), new CustomResourceReloader());
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ordering is now specified akin to events:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;ResourceLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ResourceType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SERVER_DATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addReloaderOrdering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;other&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;other_reloader_to_depend&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Triggers first&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;modid&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;custom_resource_reloader&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Triggers second&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also order based on Vanilla reloaders thanks to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceReloaderKeys&lt;/code&gt;, which provides both per-resource-reloader an identifier, and two global keys: before and after vanilla.&lt;/p&gt;

&lt;p&gt;Thanks to 1.21.9 Vanilla changes the way to register reloaders which need registry access has been simplified, instead of using a specialized registration method, now you can get registries and feature flags in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceType.SERVER_DATA&lt;/code&gt; reloaders via the shared state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DataReloader&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ResourceReloader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CompletableFuture&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Executor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prepareExecutor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Synchronizer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reloadSynchronizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Executor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;applyExecutor&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;RegistryWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;WrapperLookup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrThrow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ResourceLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;RELOADER_REGISTRY_LOOKUP_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;FeatureSet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;featureSet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrThrow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ResourceLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;RELOADER_FEATURE_SET_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Code&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This change also allows for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceReloader&lt;/code&gt;s to communicate data between them.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;https://github.com/FabricMC/fabric/issues/4574&quot;&gt;#4574&lt;/a&gt; for more details about what else is planned and the current progress.&lt;/p&gt;

&lt;h3 id=&quot;enchantments&quot;&gt;Enchantments&lt;/h3&gt;
&lt;p&gt;Transitive access wideners have been added for all of the utility methods in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentHelper&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enchantment&lt;/code&gt;. We hope that this will make it easier for developers to implement custom enchantment effect components.
See &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4819&quot;&gt;#4819&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h3 id=&quot;serialization&quot;&gt;Serialization&lt;/h3&gt;
&lt;p&gt;We have added a new module for utilities related to serialization. Currently, this module includes additional methods in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadView&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteView&lt;/code&gt;, and provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codec&lt;/code&gt;s for some types that base vanilla doesn’t. Please feel free to suggest anything else that may be useful in this area.
See &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4745&quot;&gt;#4745&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h3 id=&quot;block-conversions&quot;&gt;Block Conversions&lt;/h3&gt;
&lt;p&gt;To closer align with vanilla code flow, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OxidizableBlocksRegistry&lt;/code&gt; now supports registering a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CopperBlockSet&lt;/code&gt; direclty. Simply call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OxidizableBlocksRegistry.registerCopperBlockSet(set)&lt;/code&gt; to register. The prior methods for block pairs are still avalible for those that prefer them.
See &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4807&quot;&gt;#4807&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StrippableBlockRegistry&lt;/code&gt; now provides multiple overloads to satisfy all your stripping needs. As before, simple conversions can be registered by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StrippableBlockRegistry.register(Block, Block)&lt;/code&gt;.  You may also call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StrippableBlockRegistry.registerCopyState(Block, Block)&lt;/code&gt; to register a stripping conversion that automatically copies all properties from the previous state, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register(Block, Block, StrippingTransformer)&lt;/code&gt; to have full control over the stripping process.
See &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4829&quot;&gt;#4829&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h3 id=&quot;gui-rendering&quot;&gt;GUI Rendering&lt;/h3&gt;
&lt;p&gt;When using a custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RenderPipeline&lt;/code&gt; to render in the GUI, vanilla may assume that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VertexFormat&lt;/code&gt; being used is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QUADS&lt;/code&gt;. Fabric now provides a way to override this behavior with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RenderPipeline.Builder.withUsePipelineDrawModeForGui&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pipeline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RenderPipeline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;snippet1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;snippet1&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withUsePipelineDrawModeForGui&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fictionalRenderInGuiInNonGuads&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pipeline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// will respect the VertexFormat set in the pipeline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;See &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4824&quot;&gt;#4824&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h3 id=&quot;mixin--mixinextras&quot;&gt;Mixin &amp;amp; MixinExtras&lt;/h3&gt;
&lt;p&gt;With version 0.17.0 of Fabric Loader, MixinExtras 5.0.0 and Fabric Mixin 0.16.3+mixin.0.8.7 are now bundled.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;MixinExtras 5.0.0 brings expressions, a new way to discribe mixins to java code in a syntax that mirrors the target, leading to mixins that are easier to maintain, more expressive, and potentially even more compatible with other mixins. See the &lt;a href=&quot;https://github.com/LlamaLad7/MixinExtras/releases/tag/0.5.0&quot;&gt;release notes&lt;/a&gt; and &lt;a href=&quot;https://github.com/LlamaLad7/MixinExtras/wiki/Expressions&quot;&gt;wiki pages&lt;/a&gt; for more details.&lt;/li&gt;
  &lt;li&gt;Fabric Mixin 0.16.3 brings many bug fixes, along with scaffolding in mixin for potential widespread performance increases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;screen-key-events&quot;&gt;Screen Key Events&lt;/h3&gt;

&lt;p&gt;With many breaking changes from mojang regarding keybindings, we’ve taken the opportunity to improve our events. Most parameters in the event have been consolidated into a context object known as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeyInput&lt;/code&gt;. The &lt;em&gt;afterMouseX&lt;/em&gt; style events now also take and return a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boolean&lt;/code&gt; representing whether the event has been consumed. Returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; from these events will prevent further vanilla handling.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4846/&quot;&gt;#4846&lt;/a&gt; and &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4620&quot;&gt;#4620&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft Changes&lt;/h2&gt;

&lt;h3 id=&quot;rendering&quot;&gt;Rendering&lt;/h3&gt;
&lt;p&gt;Almost all world rendering has been reworked to group objects with similar rendering requirements together. Most places now use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OrderedRenderCommandQueue&lt;/code&gt; to submit things to be drawn later, when all objects of a similar type have been rendered.&lt;/p&gt;

&lt;h4 id=&quot;block-entities&quot;&gt;Block Entities&lt;/h4&gt;
&lt;p&gt;Block entities now use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OrderedRenderCommandQueue&lt;/code&gt;. The following example shows rendering text on the block using the queue.&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestBlockEntityRenderer&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlockEntityRenderer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TestBlockEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlockEntityRenderState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;TestBlockEntityRenderer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BlockEntityRendererFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlockEntityRenderState&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createRenderState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BlockEntityRenderState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BlockEntityRenderState&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MatrixStack&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;OrderedRenderCommandQueue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CameraRenderState&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cameraRenderState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;submitText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;matrices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;asOrderedText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;TextRenderer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TextLayerType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NORMAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lightmapCoordinates&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;WHITE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLACK&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;!-- this looks like the old way of doing this, should probably mention that --&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestBlockEntityRenderer&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlockEntityRenderer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TestBlockEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;TestBlockEntityRenderer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BlockEntityRendererFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TestBlockEntity&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tickProgress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MatrixStack&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VertexConsumerProvider&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertexConsumers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;overlay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vec3d&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cameraPos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;MinecraftClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;textRenderer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;drawWithOutline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;asOrderedText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;WHITE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLACK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;matrices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;peek&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getPositionMatrix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;vertexConsumers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;particles&quot;&gt;Particles&lt;/h4&gt;
&lt;p&gt;Particle rendering has been changed to use the same queue system as above. Many good examples for implementing custom rendering via the queue can be found in the vanilla particle classes.
&lt;!-- no examples, I'm not awake enough to be trusted with a buffer. --&gt;&lt;/p&gt;

&lt;h4 id=&quot;entities&quot;&gt;Entities&lt;/h4&gt;
&lt;p&gt;Entity rendering has changed to use the same queue as shown above. Changes will be similar.&lt;/p&gt;

&lt;h3 id=&quot;keybinding-changes&quot;&gt;Keybinding Changes&lt;/h3&gt;
&lt;p&gt;Keybinding categories have become more structured. You could do the following before:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModKeybindings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;KeyBinding&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RANDOM_KEYBIND&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;KeyBinding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;key.test.random_keybind&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;InputUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;KEYSYM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;InputUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;UNKNOWN_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;key.category.test.main&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tickKeybindings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MinecraftClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RANDOM_KEYBIND&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;wasPressed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Random keybind pressed!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;ClientTickEvents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;END_CLIENT_TICK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;ModKeybindings:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tickKeybindings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now you could do:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModKeybindings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;KeyBinding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TEST_CATEGORY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;KeyBinding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Category&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;KeyBinding&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RANDOM_KEYBIND&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;KeyBinding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;key.test.random_keybind&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;InputUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;KEYSYM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;InputUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;UNKNOWN_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;TEST_CATEGORY&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Each category may only be registered once; Registering a category twice, or two categories with the same id will lead to an exception.&lt;/p&gt;

&lt;p&gt;When Fabric API is installed, mod-provided categories will be sorted by alphabetically according to their identifiers, first by namespace, and then by path. All vanilla categories will remain in their natural order.&lt;/p&gt;

&lt;h3 id=&quot;debug-text-api&quot;&gt;Debug Text API&lt;/h3&gt;
&lt;p&gt;It is now possible to register debug HUD entries to be added to the debug (F3) overlay. The debug overlay is now also available outside of a world. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DebugHudEntries&lt;/code&gt; to register entries to be rendered as follows:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;DebugHudEntries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DebugHudEntry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;DebugHudLines&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;World&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WorldChunk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clientChunk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WorldChunk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;world&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addLine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Example in-world line :)&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addLine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Example out-of-world line :(&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;canShow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reducedDebugInfo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// return false if your debug text &lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// is not applicable with reduced debug info&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;misc&quot;&gt;Misc&lt;/h3&gt;
&lt;h4 id=&quot;macos&quot;&gt;MacOS&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MinecraftClient.IS_SYSTEM_MAC&lt;/code&gt; has been replaced by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SystemKeycodes.IS_MAC_OS&lt;/code&gt;.&lt;/p&gt;</content><author><name></name></author><summary type="html">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.</summary></entry><entry><title type="html">Fabric for Minecraft 1.21.6, 1.21.7 &amp;amp; 1.21.8</title><link href="https://fabricmc.net/2025/06/15/1216.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.21.6, 1.21.7 &amp;amp; 1.21.8" /><published>2025-06-15T00:00:00+00:00</published><updated>2025-06-15T00:00:00+00:00</updated><id>https://fabricmc.net/2025/06/15/1216</id><content type="html" xml:base="https://fabricmc.net/2025/06/15/1216.html">&lt;p&gt;A new version of Minecraft is coming soon with some changes that affect most mod makers. As always, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version.&lt;/strong&gt; We kindly ask everyone not to pester them. &lt;strong&gt;We also recommend all players make backups of their worlds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;
&lt;p&gt;Developers should use Loom 1.10 (at the time of writing) to develop mods for Minecraft 1.21.6.
Players should install the latest stable version of Fabric Loader (currently 0.16.14).&lt;/p&gt;

&lt;h3 id=&quot;deprecations-and-removals&quot;&gt;Deprecations and removals&lt;/h3&gt;
&lt;p&gt;The following previously deprecated modules have been removed (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4651&quot;&gt;#4651&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-command-api-v1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-commands-v0&lt;/code&gt; (Deprecated almost 5 years ago!)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-keybindings-v0&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-rendering-data-attachment-v1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following modules have been merged into other modules for simplicity:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-client-tags-api-v1&lt;/code&gt; was merged into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-tag-api-v1&lt;/code&gt; (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4647&quot;&gt;#4647&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-blockrenderlayer-v1&lt;/code&gt; was merged into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-rendering-v1&lt;/code&gt; (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4675&quot;&gt;#4675&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tag API changes are technically breaking for some developers who explicitly depend on these modules. The removal and merging of these modules has been done to help improve peformance when setting up a new development environment.&lt;/p&gt;

&lt;p&gt;The Fabric Rendering API previously provided a Material API, to allow modders more control of the way their models rendered. This has been removed.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Materials were removed … because they were deemed to be an unnecessary part of the API design, and the breaking change induced by changes in 1.21.6 was related to materials, which made this the perfect time to remove them - PepperCode1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4675&quot;&gt;#4675&lt;/a&gt;) for more info.&lt;/p&gt;

&lt;p&gt;In addition to being relocated, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockRenderLayerMap&lt;/code&gt; API was also updated to be more consistent out current API style:&lt;/p&gt;
&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ import net.fabricmc.fabric.api.client.rendering.v1.BlockRenderLayerMap;
&lt;/span&gt; ...
&lt;span class=&quot;gd&quot;&gt;- BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.MY_EPIC_BLOCK, BlockRenderLayer.CUTOUT)
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ BlockRenderLayerMap.putBlock(ModBlocks.MY_EPIC_BLOCK, BlockRenderLayer.CUTOUT)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;See (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4664&quot;&gt;#4664&lt;/a&gt;) for more info.&lt;/p&gt;
&lt;h3 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h3&gt;

&lt;p&gt;Fabric’s brand new HUD API had to be totally rewritten in 1.21.6. The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HudElementRegistry&lt;/code&gt; provides all of the functionality provided by the old API. The following basic example shows how you can draw text after all of the vanilla HUD layers:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;HudElementRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addLast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hud&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tickCounter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;drawTextWithShadow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MinecraftClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;textRenderer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;This is an example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;WHITE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you wish to render your custom hud element before the vanilla chat you can do the following:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;HudElementRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;attachElementBefore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;VanillaHudElements&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CHAT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ud&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tickCounter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;new-fabric-api-features&quot;&gt;New Fabric API features&lt;/h3&gt;

&lt;p&gt;Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item#appendTooltip&lt;/code&gt; has become deprecated, Fabric API now provides the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentTooltipAppenderRegistry&lt;/code&gt;. This registry provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addAfter&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addBefore&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addFirst&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addLast&lt;/code&gt; to allow you to position your tooltips relative to vanilla and other mods.&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MyAmazingComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TooltipAppender&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;appendTooltip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TooltipContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Consumer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textConsumer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TooltipType&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ComponentsAccess&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;textConsumer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Amazingness Awaits!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;ComponentType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MyAmazingComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myAmazingComponentComponentType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/*...*/&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;ComponentTooltipAppenderRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addAfter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DAMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;myAmazingComponentComponentType&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt; that has your component applied will call your component’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;appendTooltip&lt;/code&gt; method, allowing you to append as you wish. (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4587&quot;&gt;#4587&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The LootTable API has been expanded to make certain extreme usages more convenient. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootTableEvents.MODIFY_DROPS&lt;/code&gt; event allows modders to customize the collective output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootTable&lt;/code&gt;s. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootTableEvents.MODIFY&lt;/code&gt; event should still be preferred when possible, for mod compatibility reasons. This event may also recurse if you generate loot from within a listener. (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4643&quot;&gt;#4643&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matchGetter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServerRecipeManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createCachedMatchGetter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RecipeType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SMELTING&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// smelt any smeltable drops from blocks broken with a diamond pickaxe&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;LootTableEvents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;MODIFY_DROPS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drops&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hasParameter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LootContextParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TOOL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hasParameter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LootContextParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLOCK_STATE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;nc&quot;&gt;ItemStack&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LootContextParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TOOL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Items&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DIAMOND_PICKAXE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getWorld&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRegistryManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;drops&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;replaceAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;matchGetter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFirstMatch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SingleStackRecipeInput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;RecipeEntry:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recipe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;craft&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;orElse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Continuing with our conventional tag API, we added new biome tags, allowing modders to differentiate biomes based on their primary wood type.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerChunkEvents.CHUNK_LEVEL_TYPE_CHANGE&lt;/code&gt; event was added to allow more control over the timing of chunk events. This event fires for changes in chunk loading level, to react to changes not previously possible without mixins. (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4541&quot;&gt;#4541&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;An event was added for attachment changes, allowing reaction to an attachment value changing. This event can be recursive in nature, as if you set an attachment value from within a listener, the event will be invoked again. Modders should use proper recursion techniques to prevent infinite recursion. (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4606&quot;&gt;#4606&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Two more events were added for players joining and leaving the game:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;AttachmentType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Instant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;JOINED_TIME&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/*...*/&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;ServerPlayerEvents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;JOIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// runs on the main thread, no need to use player.getServer().execute(() -&amp;gt; ...);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAttached&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;JOINED_TIME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Instant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ServerPlayerEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;activePlayers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/*...*/&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;ServerPlayerEvents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;LEAVE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;activePlayers:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;These events are designed for initializing and de-initializing state related to players, and run along vanilla code with the same purpose on the main thread, unlike the current events. (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4642&quot;&gt;#4642&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricSoundsProvider&lt;/code&gt; class was added to allow convenient creation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounds.json&lt;/code&gt; from within datagen. (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4560&quot;&gt;#4560&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The Client Game Test API has been tweaked to support filtering tests run by model, allowing more precise and efficient testing. (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4597&quot;&gt;#4597&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The Model Loading API now supports registering extra unbound models (&lt;a href=&quot;https://github.com/FabricMC/fabric/pull/4565&quot;&gt;#4565&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// A ModelKey is a unique identifier for a model you want to bake.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModelKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BlockStateModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HALF_RED_SAND_MODEL_KEY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModelKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HALF_RED_SAND_MODEL_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;half_red_sand&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nc&quot;&gt;ModelLoadingPlugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pluginContext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;pluginContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HALF_RED_SAND_MODEL_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HALF_RED_SAND_MODEL_ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;nc&quot;&gt;ModelTextures&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textures&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTextures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SimpleBlockStateModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GeometryBakedModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bakeGeometry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ModelRotation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;X0_Y0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAmbientOcclusion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParticleTexture&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlockStateModel&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MinecraftClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBakedModelManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HALF_RED_SAND_MODEL_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricTrackedDataRegistry&lt;/code&gt; has been added to allow registering tracked data handlers for entities. This removes conflicts between mods registering tracked data handlers and ensures that the order is consistent between the client and server. If you previously used the vanilla API the following 1 line change is all you need to take advantage of this new API:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- TrackedDataHandlerRegistry.register(TRACKED_DATA_HANDLER);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ FabricTrackedDataRegistry.registerHandler(TRACKED_DATA_HANDLER_ID, TRACKED_DATA_HANDLER);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;bug-fixes&quot;&gt;Bug Fixes&lt;/h3&gt;
&lt;p&gt;Thanks to the diligent developers and players, many bugs in Fabric API were reported and patched during this update cycle. See &lt;a href=&quot;https://github.com/FabricMC/fabric/pulls?q=is%3Apr+is%3Aclosed+label%3Abug&quot;&gt;The Fabric Github&lt;/a&gt; for more info.&lt;/p&gt;
&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;
&lt;h3 id=&quot;rendering&quot;&gt;Rendering&lt;/h3&gt;
&lt;p&gt;Mojang is currently working on separating Minecraft’s rendering pipeline into two stages:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;The extraction stage, where all renderable data is seperated from the game&lt;/li&gt;
  &lt;li&gt;The render phase, where the previously extracted data is rendered.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process began in 1.21.2, and is still incomplete as of this update. Chunk, GUI and HUD rendering have all been converted to use the new separate rendering style. The ultimate goal of this separation is to enable the game to render one frame while the next is being extracted.&lt;/p&gt;

&lt;p&gt;Many methods in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RenderSystem&lt;/code&gt; have been removed without direct replacement. In most cases, there isn’t a one-to-one translation from the old code to the new, but the same capabilities exist by combining the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RenderPipeline&lt;/code&gt;s with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RenderLayer&lt;/code&gt;s.&lt;/p&gt;

&lt;h3 id=&quot;nbt&quot;&gt;NBT&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockEntity&lt;/code&gt;s now abstract saving to NBT through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadView&lt;/code&gt;s and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteView&lt;/code&gt;s. These views are responsible for storing errors from encoding / decoding, and keeping track of registries throughout the serialization process. You can read from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadView&lt;/code&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; method, passing in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codec&lt;/code&gt; for the desired type. Likewise, you can write to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteView&lt;/code&gt; by using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;put&lt;/code&gt; method, passing in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codec&lt;/code&gt; for the type, and the value in question. there are also methods for primitives, under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get(Int, Short, Boolean, ...)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;put(Int, Short, Boolean, ...)&lt;/code&gt;. The View also provides methods for working with lists, nullable types, and nested objects.&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BE&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlockEntity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Extra&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// Ctor excluded for brevity&lt;/span&gt;
	&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NbtCompound&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toInitialChunkDataNbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;WrapperLookup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createNbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// createNbt takes care of adapting to / from WriteView&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;writeData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;WriteView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;writeData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;putNullable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;extra&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// putString will eventually throw if we pass null&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;putString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aString&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;putInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anInt&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;readData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ReadView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;extra&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ifPresent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOptionalString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aString&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ifPresent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;aString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOptionalInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anInt&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ifPresent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anInt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;anInt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CODEC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RecordCodecBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fieldOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;i&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forGetter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fieldOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;j&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forGetter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Extra:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;data-generation&quot;&gt;Data Generation&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOrCreateTagBuilder&lt;/code&gt; should be replaced with the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valueLookupBuilder&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">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.</summary></entry><entry><title type="html">Fabric for Minecraft 1.21.5</title><link href="https://fabricmc.net/2025/03/24/1215.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.21.5" /><published>2025-03-24T00:00:00+00:00</published><updated>2025-03-24T00:00:00+00:00</updated><id>https://fabricmc.net/2025/03/24/1215</id><content type="html" xml:base="https://fabricmc.net/2025/03/24/1215.html">&lt;p&gt;A new version of Minecraft is coming soon with some changes that affect most mod makers. As always, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version.&lt;/strong&gt; We kindly ask everyone not to pester them. &lt;strong&gt;We also recommend all players make backups of their worlds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;
&lt;p&gt;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).&lt;/p&gt;

&lt;h3 id=&quot;loom-110&quot;&gt;Loom 1.10&lt;/h3&gt;
&lt;p&gt;Loom 1.10 requires Gradle 8.12, and comes with performance improvements and enhanced testing setup support. You can checkout the new Loom documentation &lt;a href=&quot;https://docs.fabricmc.net/develop/loom/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;deprecations-and-removals&quot;&gt;Deprecations and removals&lt;/h3&gt;
&lt;p&gt;In Content Registries, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerInteractionsRegistries#registerGiftLootTable&lt;/code&gt; overload that takes an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt; was removed. This method was previously deprecated.&lt;/p&gt;

&lt;p&gt;In Object Builder, two deprecated classes, namely &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerProfessionBuilder&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerTypeHelper&lt;/code&gt;, have been removed. Use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerProfession&lt;/code&gt; constructor and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerType#create&lt;/code&gt; instead. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TradeOfferHelper#refreshOffers&lt;/code&gt;, which had been deprecated and did nothing, was also removed.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HudRenderCallback&lt;/code&gt; has been deprecated in favor of newly added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HudLayerRegistrationCallback&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h3&gt;
&lt;p&gt;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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example:potato_variant&lt;/code&gt;, the file for variant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test:tiny&lt;/code&gt; will be placed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data/test/example/potato_variant/tiny.json&lt;/code&gt;.&lt;!-- https://github.com/FabricMC/fabric/pull/4180 --&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiomeModificationContext#addSpawn&lt;/code&gt; has a new parameter, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;weight&lt;/code&gt;. This was previously part of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpawnEntry&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TradeOfferHelper&lt;/code&gt; now takes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&lt;/code&gt; of the profession instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerProfession&lt;/code&gt;. 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.)&lt;/p&gt;

&lt;h3 id=&quot;new-fabric-api-changes&quot;&gt;New Fabric API changes&lt;/h3&gt;
&lt;p&gt;With the help of many contributors, Fabric API has received some new features since the last update blog post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;New module: Client Game Test API, which can be used to automatically test client rendering and GUI (Earthcomputer)&lt;/li&gt;
  &lt;li&gt;New module: Fabric Tag API, which currently handles tag aliases (Juxxel)&lt;/li&gt;
  &lt;li&gt;Convention Tags: Sync remaining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt; tags with NeoForge (TelepathicGrunt)&lt;/li&gt;
  &lt;li&gt;Convention Tags: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c:flowers&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c:flowers/tall&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c:flowers/small&lt;/code&gt; block and item tags (TelepathicGrunt)&lt;/li&gt;
  &lt;li&gt;Convention Tags: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TagKey&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c:tools/wrench&lt;/code&gt; (TelepathicGrunt)&lt;/li&gt;
  &lt;li&gt;Convention Tags: Convention Drink Tags (TheDeathlyCow)&lt;/li&gt;
  &lt;li&gt;Convention Tags: Add Pumpkin Block and Item Tags (JT122406)&lt;/li&gt;
  &lt;li&gt;Data Generation: Add vararg helper methods for multi-tag support in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricTagBuilder&lt;/code&gt; (Starexify)&lt;/li&gt;
  &lt;li&gt;Data Generation: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricEntityLootTableProvider&lt;/code&gt; (Antikyth)&lt;/li&gt;
  &lt;li&gt;Item API: Add a method for overriding modelId in item settings (Patbox)&lt;/li&gt;
  &lt;li&gt;Item API: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contains&lt;/code&gt; method to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricComponentMapBuilder&lt;/code&gt; (TheDeathlyCow)&lt;/li&gt;
  &lt;li&gt;Item Group API: Change Creative Buttons Texture (matthewperiut)&lt;/li&gt;
  &lt;li&gt;Item Group API: Use page up/down to change creative inventory pages (modmuss50)&lt;/li&gt;
  &lt;li&gt;Model Loading API: Allow retrieving model loading plugins (PepperCode1)&lt;/li&gt;
  &lt;li&gt;Networking API: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerPlayNetworking.reconfigure&lt;/code&gt; (modmuss50)&lt;/li&gt;
  &lt;li&gt;Object Builder: Allow setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canPotentiallyExecuteCommands&lt;/code&gt; in builders (PepperCode1)&lt;/li&gt;
  &lt;li&gt;Recipe API: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAllMatches&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAllOfType&lt;/code&gt; methods to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerRecipeManager&lt;/code&gt; (Patbox)&lt;/li&gt;
  &lt;li&gt;Registry Sync: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryAttribute#OPTIONAL&lt;/code&gt; that can be used to not disconnect clients lacking an entire registry; note that optional registry values are still unsupported (modmuss50)&lt;/li&gt;
  &lt;li&gt;Registry Sync: Registry aliasing (Syst3ms)&lt;/li&gt;
  &lt;li&gt;Rendering: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpecialBlockRendererRegistry&lt;/code&gt; (PepperCode1)&lt;/li&gt;
  &lt;li&gt;Rendering: Add HUD Render Events (kevinthegreat1)&lt;/li&gt;
  &lt;li&gt;Resource Loader: Implement builtin mod resource/data pack sorting (Apollo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;tag-and-registry-aliases&quot;&gt;Tag and registry aliases&lt;/h3&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addAlias&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my_mod&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;old&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my_mod&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;new&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Tag aliases are defined in data packs like tags. For example, a block tag alias group for fences would be located at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data/my_mod/fabric/tag_aliases/block/fences.json&lt;/code&gt; with the contents:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:fences&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;c:fences&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;client-gametest&quot;&gt;Client GameTest&lt;/h3&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;World creation API, for specifying options used to generate the test world.&lt;/li&gt;
  &lt;li&gt;Screenshot API, with support for comparing against golden images.&lt;/li&gt;
  &lt;li&gt;Input API, to simulate a user interacting with the game.&lt;/li&gt;
  &lt;li&gt;Advanced threading setup, to make the tests more repoducible.&lt;/li&gt;
  &lt;li&gt;Network synchronization, to ensure packets are handled consistently.&lt;/li&gt;
  &lt;li&gt;Herobrine removal, to bring peace to the Kingdom of Tiny Potato.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more information checkout the full documentation &lt;a href=&quot;https://maven.fabricmc.net/docs/fabric-api-0.119.2+1.21.5/net/fabricmc/fabric/api/client/gametest/v1/package-summary.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;hud-render-events&quot;&gt;HUD Render Events&lt;/h3&gt;
&lt;p&gt;Fabric API 0.116.0 added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HudLayerRegistrationCallback&lt;/code&gt; 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!&lt;/p&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;
&lt;h3 id=&quot;nbt&quot;&gt;NBT&lt;/h3&gt;
&lt;p&gt;Significant changes to NBT handling code have been made.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NbtCompound&lt;/code&gt; methods now return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt; 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.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- int value = nbt.getInt(&quot;value&quot;);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ Optional&amp;lt;Integer&amp;gt; value = nbt.getInt(&quot;value&quot;); // not OptionalInt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; methods:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- int value;
- if (nbt.contains(&quot;value&quot;, NbtElement.NUMBER_TYPE)) {
-   value = nbt.getInt(&quot;value&quot;);
- } else {
-   value = 1000;
- }
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ int value = nbt.getInt(&quot;value&quot;, 1000);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NbtElement#NUMBER_TYPE&lt;/code&gt; and type-aware &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contains&lt;/code&gt; have been removed. There is no fallback method for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getIntArray&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getLongArray&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getByteArray&lt;/code&gt;. (Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional#orElse&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getCompound&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getList&lt;/code&gt; methods, methods with the previous behavior (returning empty objects) are provided with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OrEmpty&lt;/code&gt; suffix.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- NbtCompound config = nbt.getCompound(&quot;config&quot;);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ NbtCompound config = nbt.getCompoundOrEmpty(&quot;config&quot;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, for those who want to encode/decode codec-based values (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt;) stored in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NbtCompound&lt;/code&gt; field, new methods simplify the process:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java=&quot;&gt;NbtCompound nbt = new NbtCompound();
nbt.put(&quot;Id&quot;, Identifier.CODEC, id);
// for reading
Optional&amp;lt;Identifier&amp;gt; id = nbt.get(&quot;Id&quot;, Identifier.CODEC);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And if there is a codec for the whole object:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java=&quot;&gt;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&amp;lt;ItemStack&amp;gt; stack = nbt.decode(ItemStack.MAP_CODEC, wrapperLookup.getOps(NbtOps.INSTANCE));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Typed arrays (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ByteArray&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IntArray&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LongArray&lt;/code&gt;) are no longer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&lt;/code&gt;s. They can be converted to a list using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.stream().toList()&lt;/code&gt;, but this is usually not necessary. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NbtList&lt;/code&gt; can now contain values of differing types, but this should be a transparent change unless you work with binary data.&lt;/p&gt;

&lt;h3 id=&quot;gametest&quot;&gt;GameTest&lt;/h3&gt;

&lt;p&gt;In Minecraft &lt;a href=&quot;https://www.minecraft.net/en-us/article/minecraft-snapshot-25w03a&quot;&gt;25w03a&lt;/a&gt;, 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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@GameTest&lt;/code&gt; annotation that functions similarly to the old one. The options in the new Fabric-provided &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@GameTest&lt;/code&gt; 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.&lt;/p&gt;

&lt;h3 id=&quot;miscellaneous&quot;&gt;Miscellaneous&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataPool&lt;/code&gt; has been replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pool&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AbstractBlock#onStateReplaced&lt;/code&gt; has been significantly changed, the state provided is the old state and it now runs after block entities get removed. Block entities should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockEntity#onBlockReplaced&lt;/code&gt; instead.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">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.</summary></entry><entry><title type="html">Fabric for Minecraft 1.21.4</title><link href="https://fabricmc.net/2024/12/02/1214.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.21.4" /><published>2024-12-02T00:00:00+00:00</published><updated>2024-12-02T00:00:00+00:00</updated><id>https://fabricmc.net/2024/12/02/1214</id><content type="html" xml:base="https://fabricmc.net/2024/12/02/1214.html">&lt;p&gt;Minecraft 1.21.4, the Garden Awakens drop, releases December 3rd. Like with other updates, this drop contains some significant changes affecting mod makers.&lt;/p&gt;

&lt;p&gt;As always, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version.&lt;/strong&gt; We kindly ask everyone not to pester them. &lt;strong&gt;We also recommend all players make backups of their worlds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;

&lt;p&gt;Developers should use Loom 1.9 (at the time of writing) to develop mods for Minecraft 1.21.4. Players should install the latest stable version of Fabric Loader (currently 0.16.9).&lt;/p&gt;

&lt;h3 id=&quot;deprecations-and-removals&quot;&gt;Deprecations and removals&lt;/h3&gt;
&lt;p&gt;The following deprecated module was removed: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-rendering-v0&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricModelPredicateProviderRegistry&lt;/code&gt;, which was previously deprecated, was also removed.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuiltinItemRenderer&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuiltinItemRendererRegistry&lt;/code&gt; from the Rendering v1 module were removed and have been replaced by a transitive access widener to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpecialModelTypes.ID_MAPPER&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttachmentRegistry#builder&lt;/code&gt; was deprecated in favor of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create&lt;/code&gt; methods. The old method is inconvenient, as it requires explicit type parameters. (See the “Data Attachment Syncing” section for an example.)&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockPickInteractionAware&lt;/code&gt; was removed, the new pick item events should be used instead.&lt;/p&gt;

&lt;h3 id=&quot;breaking-change&quot;&gt;Breaking change&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomIngredient#getMatchingStacks&lt;/code&gt; must now return a stream, not a list.&lt;/p&gt;

&lt;!-- NOTE: despite what the semver suggests, Biome API DID NOT receive a breaking change in 24w44a. --&gt;

&lt;h3 id=&quot;new-fabric-api-changes&quot;&gt;New Fabric API changes&lt;/h3&gt;

&lt;p&gt;With the help of many contributors, Fabric API has received some new features since the last update blog post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Convention Tags: Add more tags (JT122406, TelepathicGrunt, IThundxr)&lt;/li&gt;
  &lt;li&gt;Data Attachments: Registration enhancements (forgetmenot13579)&lt;/li&gt;
  &lt;li&gt;Data Attachments: Sync API (Syst3ms)&lt;/li&gt;
  &lt;li&gt;Lifecycle Events: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerChunkEvents.Generate&lt;/code&gt; (jpenilla)&lt;/li&gt;
  &lt;li&gt;Lifecycle Events: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AFTER_CLIENT_WORLD_CHANGE&lt;/code&gt; (fishshi)&lt;/li&gt;
  &lt;li&gt;Transfer API: Add support for Item-containing Items (BasiqueEvangelist)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, a longstanding bug that caused language files to not load after overriding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/minecraft/lang/en_us.json&lt;/code&gt; in a dedicated server mod was fixed.&lt;/p&gt;

&lt;h4 id=&quot;data-attachment-syncing&quot;&gt;Data Attachment Syncing&lt;/h4&gt;
&lt;p&gt;Fabric API can now sync data attachments. To make a syncable attachment, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syncWith&lt;/code&gt; inside the builder. The passed packet codec is used to serialize the attached data. Here is how a thirst attachment would look like:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AttachmentType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;THIRST&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AttachmentRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;modid&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;thirst&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt; 
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;initializer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// start with a default value like hunger&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persistent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// persist across restarts&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;syncWith&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;VAR_INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AttachmentSyncPredicate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;targetOnly&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// only the player's own client needs the value for rendering&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The sync predicate (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttachmentSyncPredicate&lt;/code&gt;) controls who gets the synced data. For example, global data can be synced using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all()&lt;/code&gt;. For more granular control, you can also pass a custom predicate.&lt;/p&gt;

&lt;h4 id=&quot;pick-item-events&quot;&gt;Pick item events&lt;/h4&gt;

&lt;p&gt;Minecraft 1.21.4 moves the ‘Pick Block’ functionality from the client to the logical server. As such, the existing client events have been replaced with new, server-side ones. This replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientPickBlockApplyCallback&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientPickBlockCallback&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientPickBlockGatherCallback&lt;/code&gt;. This change also applies to entities (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityPickInteractionAware&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The new events are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PlayerPickItemEvents#BLOCK&lt;/code&gt; for picking a block and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PlayerPickItemEvents#ENTITY&lt;/code&gt; for picking an entity(‘s spawn egg). Return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack.EMPTY&lt;/code&gt; to stop the picking, and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; to use the default behavior.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;PlayerPickItemEvents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestIncludeData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isIn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MyTags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NOT_PICKABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ItemStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;EMPTY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// use default behavior&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestIncludeData&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; if the client requests NBT to be included in the returned item stack (by holding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; while picking block). This parameter is also available to the entity pick item event, even though vanilla does not use this functionality (spawn eggs do not include the picked entity’s NBT).&lt;/p&gt;

&lt;p&gt;Note that this only checks if the client is asking NBT data, and does not check game mode or permission level. In vanilla, NBT data is only included for Creative mode players.&lt;/p&gt;

&lt;h4 id=&quot;client-data-generation&quot;&gt;Client Data Generation&lt;/h4&gt;

&lt;p&gt;Starting with Minecraft 1.21.4, Mojang has moved a number of data generation classes to the client. Loom 1.9 adds a new option that allows you to run your data generation against the client. See the following example if you are using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabricApi&lt;/code&gt; utility to set up data generation:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  fabricApi {
&lt;span class=&quot;gd&quot;&gt;-     configureDataGeneration()
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+     configureDataGeneration {
+       client = true
+     }
&lt;/span&gt;  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you are using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createSourceSet&lt;/code&gt; option, your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;datagen&lt;/code&gt; source set will now have access to Minecraft’s client-only classes and classes in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client&lt;/code&gt; source set. Other than updating the data generators themselves, no other changes will be necessary.&lt;/p&gt;

&lt;p&gt;If you are using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;splitEnvironmentSourceSets&lt;/code&gt; option but not the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createSourceSet&lt;/code&gt; option, you should move your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataGeneratorEntrypoint&lt;/code&gt; implementation from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; source set to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client&lt;/code&gt; source set.&lt;/p&gt;

&lt;h4 id=&quot;model-loading-api&quot;&gt;Model Loading API&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModelModifier&lt;/code&gt; events and callbacks have been split; there is now one set for static models and one set for block models. This was necessary because static models use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnbakedModel&lt;/code&gt; and are baked with settings while block models use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GroupableModel&lt;/code&gt; (which no longer extends &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnbakedModel&lt;/code&gt;) and are not baked with settings. It also allowed cleaning up the identifier getters and providing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockState&lt;/code&gt; directly to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModelModifier.OnLoadBlock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeforeBake&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AfterBake&lt;/code&gt; events were removed. This is because their behavior can now be achieved using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnLoad&lt;/code&gt; events, by wrapping the given model and overriding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bake&lt;/code&gt; method to replace the unbaked model passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super.bake&lt;/code&gt; (to replicate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeforeBake&lt;/code&gt;) or replace the result of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super.bake&lt;/code&gt; (to replicate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AfterBake&lt;/code&gt;). This is possible because 1.21.4 made it so the parent of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JsonUnbakedModel&lt;/code&gt; no longer has to be another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JsonUnbakedModel&lt;/code&gt;. To make this easier, the utility classes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WrapperUnbakedModel&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WrapperGroupableModel&lt;/code&gt; were added, which forward all method calls to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wrapper&lt;/code&gt; field. There were also some minor fundamental issues with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeforeBake&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AfterBake&lt;/code&gt; events, which prompted their removal.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModelModifier.OnLoad&lt;/code&gt; can now accept a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; model, which is a model that was requested during resolution but does not have a corresponding JSON file. With this change, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModelResolver&lt;/code&gt; was removed as its behavior could now be achieved with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModelModifier.OnLoad&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OVERRIDE_PHASE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DelegatingUnbakedModel&lt;/code&gt; was removed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GroupableModel&lt;/code&gt; no longer extends &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnbakedModel&lt;/code&gt;, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockModelResolver&lt;/code&gt;s can no longer use it, which was its original purpose.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;textureGetter&lt;/code&gt; was removed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModelModifier&lt;/code&gt; callback contexts as it is now accessible through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Baker#getSpriteGetter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;FRAPI’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WrapperBakedModel&lt;/code&gt; was moved to Model Loading API and was renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnwrappableBakedModel&lt;/code&gt; to avoid conflicts with vanilla’s new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WrapperBakedModel&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnwrappableBakedModel&lt;/code&gt; is also implemented and interface injected on vanilla’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WrapperBakedModel&lt;/code&gt;. A new static &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnwrappableBakedModel#unwrap&lt;/code&gt; method was added which accepts a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Predicate&lt;/code&gt; saying when to stop unwrapping. See the documentation for more details.&lt;/p&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;

&lt;h3 id=&quot;block-models&quot;&gt;Block Models&lt;/h3&gt;

&lt;p&gt;Previously, block entities could choose whether they rendered their block model in addition to any custom block entity rendering. This method has been removed, as now all block entities render their block models:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- @Override
- protected BlockRenderType getRenderType(BlockState state) {
-     return BlockRenderType.ENTITYBLOCK_ANIMATED;
- }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While block models were already used to provide particle textures in these cases, mods should still ensure their block entities’ block models are correct.&lt;/p&gt;

&lt;h3 id=&quot;item-models&quot;&gt;Item Models&lt;/h3&gt;

&lt;p&gt;Similar to the blockstate definition json files found in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/&amp;lt;namespace&amp;gt;/blockstates&lt;/code&gt;, items now utilize new item model definition json files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/&amp;lt;namespace&amp;gt;/items&lt;/code&gt; to determine which models to use.&lt;/p&gt;

&lt;p&gt;These can be quite simple…&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;modid:item/my_item&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;or more complex…&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:condition&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;property&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:fishing_rod/cast&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;on_false&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;modid:item/netherite_fishing_rod&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;on_true&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;modid:item/netherite_fishing_rod_cast&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;utilising conditions and other logic to determine which model to use.&lt;/p&gt;

&lt;p&gt;They also control applying color tints to item textures.&lt;/p&gt;
&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:item/template_spawn_egg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tints&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:constant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6925483&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minecraft:constant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12238402&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These tints can be constant or based on other factors such as potion contents, map colors, etc.&lt;/p&gt;

&lt;p&gt;As a result of these files being introduced, blocks whose item models previously simply referred to their block model no longer require a separate item model file, as the block model is referred to in the model definition file instead. For example,&lt;/p&gt;
&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- {
-  &quot;parent&quot;: &quot;modid:block/maple_planks&quot;
- }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/modid/models/item/maple_planks.json&lt;/code&gt; can be removed, in favor of&lt;/p&gt;
&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gi&quot;&gt;+ {
+  &quot;model&quot;: {
+    &quot;type&quot;: &quot;minecraft:model&quot;,
+    &quot;model&quot;: &quot;modid:block/maple_planks&quot;
+  }
+ }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/modid/items/maple_planks.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemColors&lt;/code&gt; and related APIs for tinting items have been removed, as item color tints are now controlled by these files.&lt;/p&gt;

&lt;p&gt;For further information, these jsons are well documented on &lt;a href=&quot;https://minecraft.wiki/w/Items_model_definition&quot;&gt;the vanilla Minecraft wiki here&lt;/a&gt; and all the ones used by vanilla items can be easily found in the game files.&lt;/p&gt;

&lt;p&gt;For modders using data generation, these can be generated much like any other JSON asset.&lt;/p&gt;

&lt;h3 id=&quot;miscellaneous&quot;&gt;Miscellaneous&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Resource Metadata files now use Codec serializers&lt;/li&gt;
  &lt;li&gt;Equipment assets were moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/&amp;lt;namespace&amp;gt;/models/equipment&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/&amp;lt;namespace&amp;gt;/equipment&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:tall_flowers&lt;/code&gt; block tag was removed&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:flowers&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:tall_flowers&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:trim_templates&lt;/code&gt; item tags were removed&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:herobrine&lt;/code&gt; entity was removed&lt;/li&gt;
  &lt;li&gt;Trim Material jsons no longer specify an item model index, as trimmed items now use separate item models for each material&lt;/li&gt;
  &lt;li&gt;Textures for item outlines shown in empty slots in certain GUIs are now located in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assets/&amp;lt;namespace&amp;gt;/textures/gui/sprites/container/slot&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;yarn-changes&quot;&gt;Yarn changes&lt;/h2&gt;

&lt;p&gt;There have been many changes to Yarn mappings to reflect refactors to the vanilla game, fix issues with the mappings, or to otherwise improve them.&lt;/p&gt;

&lt;p&gt;Some notable examples include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net/minecraft/data/client&lt;/code&gt; package got moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net/minecraft/client/data&lt;/code&gt;, to reflect the classes now being client-only&lt;/li&gt;
  &lt;li&gt;To match this, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net/minecraft/data/server&lt;/code&gt; package was removed and its contents moved down to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net/minecraft/data&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;All references to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xp&lt;/code&gt; got changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;experience&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockStateModelGenerator.TintType&lt;/code&gt; was changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockStateModelGenerator.CrossType&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CherryLeavesBlock&lt;/code&gt; was changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParticleLeavesBlock&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CherryLeavesParticle&lt;/code&gt; was changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LeavesParticle&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LichenGrower&lt;/code&gt; was changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MultifaceGrower&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityModelLoader&lt;/code&gt; was changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoadedEntityModels&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CocoaBeansTreeDecorator&lt;/code&gt; was changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CocoaTreeDecorator&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BakedQuad#colorIndex&lt;/code&gt; was changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tintIndex&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">Minecraft 1.21.4, the Garden Awakens drop, releases December 3rd. Like with other updates, this drop contains some significant changes affecting mod makers.</summary></entry><entry><title type="html">Fabric for Minecraft 1.21.2 &amp;amp; 1.21.3</title><link href="https://fabricmc.net/2024/10/14/1212.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.21.2 &amp;amp; 1.21.3" /><published>2024-10-14T00:00:00+00:00</published><updated>2024-10-14T00:00:00+00:00</updated><id>https://fabricmc.net/2024/10/14/1212</id><content type="html" xml:base="https://fabricmc.net/2024/10/14/1212.html">&lt;p&gt;Minecraft 1.21.2, the “Bundles of Bravery” drop, is expected to release soon. Mojang has recently &lt;a href=&quot;https://www.minecraft.net/en-us/article/the-future-of-minecrafts-development&quot;&gt;announced&lt;/a&gt; that they will release these “drops” throughout the year. Like with other updates, this drop contains some significant changes affecting mod makers.&lt;/p&gt;

&lt;p&gt;As always, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version.&lt;/strong&gt; We ask everyone kindly not to pester them. &lt;strong&gt;We also recommend all players to make a backup of their worlds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;

&lt;p&gt;Developers should use Loom 1.8 (at the time of writing) to develop mods for Minecraft 1.21.2. Players should install the latest stable version of Fabric Loader (currently 0.16.7).&lt;/p&gt;

&lt;h3 id=&quot;fabric-loader-changes&quot;&gt;Fabric Loader changes&lt;/h3&gt;

&lt;p&gt;Fabric Loader 0.16.0 was released some time ago.  Most notably, this release updates the bundled MixinExtras to 0.4.0.&lt;/p&gt;

&lt;p&gt;In addition, Fabric Loader 0.16.7 added support for Java 23. However, you should continue to use Java 21 for mod development and gameplay.&lt;/p&gt;

&lt;h4 id=&quot;mixinextras-additions&quot;&gt;MixinExtras additions&lt;/h4&gt;

&lt;p&gt;The following new features have been added:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/LlamaLad7/MixinExtras/wiki/WrapMethod&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@WrapMethod&lt;/code&gt;&lt;/a&gt;, which allows wrapping the entire method&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/LlamaLad7/MixinExtras/wiki/Cancellable&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Cancellable&lt;/code&gt;&lt;/a&gt;, which allows cancellation from all injectors.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace&lt;/code&gt; parameter in &lt;a href=&quot;https://github.com/LlamaLad7/MixinExtras/wiki/Share&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Share&lt;/code&gt;&lt;/a&gt; to share values between Mixins&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;loom-18&quot;&gt;Loom 1.8&lt;/h3&gt;

&lt;p&gt;Loom 1.8 adds support for configuration caches, Gradle 8.10, and other changes and fixes.&lt;/p&gt;

&lt;p&gt;Configuration cache is an opt-in Gradle performance enhancement feature that will be enabled by default in Gradle 9. Because this may break existing setup, we only recommend using this if you are familiar with Gradle buildscripts. To support this change, multi-project optimization has been removed.&lt;/p&gt;

&lt;h3 id=&quot;new-fabric-api-changes&quot;&gt;New Fabric API changes&lt;/h3&gt;

&lt;p&gt;With the help of many contributors, Fabric API has received some new features since the last update blog post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Convention Tags: Add more tags (TelepathicGrunt, Juuz)&lt;/li&gt;
  &lt;li&gt;Crash Report Info: Print the full stack trace from the dedicated server watchdog (TelepathicGrunt)&lt;/li&gt;
  &lt;li&gt;Entity Events: Add after damage event (TheDeathlyCow)&lt;/li&gt;
  &lt;li&gt;Item API: Modify enchantment and add component map builder extensions (TheDeathlyCow)&lt;/li&gt;
  &lt;li&gt;Item Group API: Add API to control creative inventory screen (modmuss50)&lt;/li&gt;
  &lt;li&gt;Loot API: Loot API v3 (modmuss50)&lt;/li&gt;
  &lt;li&gt;Networking: Add MinecraftClient/Server instances to networking contexts (modmuss50)&lt;/li&gt;
  &lt;li&gt;Networking: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientConfigurationConnectionEvents#START&lt;/code&gt; (modmuss50)&lt;/li&gt;
  &lt;li&gt;Networking: Add access to ClientConfigurationNetworkHandler in context (Earthcomputer)&lt;/li&gt;
  &lt;li&gt;Object Builder: Add an API to add additional supported blocks to block entity types (modmuss50)&lt;/li&gt;
  &lt;li&gt;Renderer API: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ShadeMode&lt;/code&gt; (PepperCode1)&lt;/li&gt;
  &lt;li&gt;Renderer API: Quads overloads for joml interfaces (SHsuperCM)&lt;/li&gt;
  &lt;li&gt;Resource Conditions: Allow conditions inside pack overlays (Apollo)&lt;/li&gt;
  &lt;li&gt;Resource Loader: Add API to create reload listeners with a registry lookup (modmuss50)&lt;/li&gt;
  &lt;li&gt;Removed Herobrine (Tiny Potato)&lt;/li&gt;
  &lt;li&gt;Transfer API: Crafter support (modmuss50)&lt;/li&gt;
  &lt;li&gt;Transfer API: Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemVariant#withComponentChanges&lt;/code&gt; (BasiqueEvangelist)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;breaking-changes-and-deprecations&quot;&gt;Breaking changes and deprecations&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Note: breaking changes related to vanilla changes are addressed separately below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One deprecated module was removed: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-renderer-registries-v1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Resource Condition, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; method now takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryOps.RegistryInfoGetter&lt;/code&gt;. Tags can no longer have resource conditions. Similarly, in Resource Loader, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceReloadListenerKeys#TAGS&lt;/code&gt; was removed.&lt;/p&gt;

&lt;p&gt;The following deprecations were made since the last blogpost:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Content Registries: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerInteractionRegistries#registerCollectable&lt;/code&gt; was deprecated. Use the vanilla tag, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:villager_picks_up&lt;/code&gt;, instead.&lt;/li&gt;
  &lt;li&gt;Loot API: Loot API v2 was deprecated. Use Loot API v3, which passes registry contexts, instead.&lt;/li&gt;
  &lt;li&gt;Networking:&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientConfigurationConnectionEvents#READY&lt;/code&gt; was renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COMPLETE&lt;/code&gt;. (This was done during the 1.21 update cycle, but after we published the last blogpost.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;

&lt;h3 id=&quot;serverworld-parameters&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerWorld&lt;/code&gt; parameters&lt;/h3&gt;

&lt;p&gt;Many methods that must be executed on the server side only now require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerWorld&lt;/code&gt; to be passed explicitly. &lt;strong&gt;Do not cast just to fix a type error;&lt;/strong&gt; many events and overridden method are still called on both the client side and the server side.&lt;/p&gt;

&lt;p&gt;Instead, wrap all logic that must be run only on the server side with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if (world instanceof ServerWorld serverWorld)&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serverWorld&lt;/code&gt; can be passed to those methods.&lt;/p&gt;

&lt;p&gt;For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Entity#damage&lt;/code&gt; now requires &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerWorld&lt;/code&gt;, and is therefore only called on the server side. There is an additional method, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clientDamage&lt;/code&gt;, which is called only on the client side.&lt;/p&gt;

&lt;h3 id=&quot;block-and-item-settings&quot;&gt;Block and item settings&lt;/h3&gt;

&lt;p&gt;Minecraft 1.21.2 uses registry keys to pre-compute certain block or item settings. This allows referencing them in default item components. For example, rather than computing a default name based on an item’s registry key inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName&lt;/code&gt; method if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:item_name&lt;/code&gt; component is not present, every item now contains the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:item_name&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Because of this, you must &lt;strong&gt;manually set registry keys in the settings of every block and item&lt;/strong&gt;. Failure to do so will result in crashes such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NullPointerException: Block id not set&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NullPointerException: Item id not set&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both settings classes provide a simple method which should be called for every item or block with their respective registry key:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mymod&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test_item&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;RegistryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RegistryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ITEM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Settings&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// If your item is based on a block&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;useBlockPrefixedTranslationKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Registry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ITEM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mymod&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test_block&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;RegistryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Block&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RegistryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Block&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Settings&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Block&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Registry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Block&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure to call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item.Settings#useBlockPrefixedTranslationKey&lt;/code&gt; method for block items so that they use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.&amp;lt;namespace&amp;gt;.&amp;lt;path&amp;gt;&lt;/code&gt; translation key format.&lt;/p&gt;

&lt;p&gt;This change affects the following traits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Item names (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:item_name&lt;/code&gt; component)&lt;/li&gt;
  &lt;li&gt;Item models (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:item_model&lt;/code&gt; component)&lt;/li&gt;
  &lt;li&gt;Block models&lt;/li&gt;
  &lt;li&gt;Block loot table key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some traits, such as the cooldown group of items with cooldowns, still dynamically look up a registry key, but this pattern should be avoided as much as possible.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Block#getLootTableKey&lt;/code&gt; now returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&amp;lt;RegistryKey&amp;gt;&lt;/code&gt;. A block without a corresponding loot table now returns an empty optional instead of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:empty&lt;/code&gt; loot table registry key.&lt;/p&gt;

&lt;p&gt;In Fabric API, the previously-deprecated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBlockSettings&lt;/code&gt; class was removed. Use the vanilla &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AbstractBlock.Settings&lt;/code&gt; class instead.&lt;/p&gt;

&lt;h3 id=&quot;furnace-fuels&quot;&gt;Furnace fuels&lt;/h3&gt;

&lt;p&gt;Furnace fuels are now registered through an event, which allows access to new parameters:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- FuelRegistry.INSTANCE.add(ModItems.TEST_ITEM, 50);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ FuelRegistryEvents.BUILD.register((builder, context) -&amp;gt; {
+     builder.add(ModItems.TEST_ITEM, context.baseSmeltTime() / 4);
+ });
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The base smelt time can be used to express a fuel’s smelt time in terms of a ratio. The default base smelt time is 200 ticks, or 10 seconds.&lt;/p&gt;

&lt;h3 id=&quot;entities&quot;&gt;Entities&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityType&lt;/code&gt; received a registry key change similar to the block and item one described above. When building an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityType&lt;/code&gt;, pass a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&lt;/code&gt; for the entity type. The no-argument version of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityType.Builder#build&lt;/code&gt; method, injected by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricEntityTypeBuilder&lt;/code&gt;, has been removed. For example:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mymod&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test_entity_type&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;RegistryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;EntityType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RegistryKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ENTITY_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;EntityType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TestEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EntityType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TestEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;TestEntity:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SpawnGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;MISC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Registry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ENTITY_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mob conversion (such as zombie villager curing or slimes splitting on death) was overhauled. The exact behavior of conversion is now handled by methods implemented by values of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityConversionType&lt;/code&gt; enum. When using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MobEntity#convertTo&lt;/code&gt; method to convert a mob, an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityConversionContext&lt;/code&gt; is now required. This context is also now passed to Fabric API’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerLivingEntityEvents#MOB_CONVERSION&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;When creating an entity, a spawn reason is now required:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- Entity pig = EntityType.PIG.create(overworld);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ Entity pig = EntityType.PIG.create(overworld, SpawnReason.SPAWN_ITEM_USE);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The prefixes of attributes in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityAttributes&lt;/code&gt;, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GENERIC&lt;/code&gt;, have been dropped. This matches a change in the identifiers of attributes:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- public static final RegistryEntry&amp;lt;EntityAttribute&amp;gt; GENERIC_ATTACK_KNOCKBACK = register(
-    &quot;generic.attack_knockback&quot;,
-    new ClampedEntityAttribute(&quot;attribute.name.generic.attack_knockback&quot;, 0, 0, 5)
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;);&lt;/span&gt;
+ public static final RegistryEntry&amp;lt;EntityAttribute&amp;gt; ATTACK_KNOCKBACK = register(
    &quot;attack_knockback&quot;,
    new ClampedEntityAttribute(&quot;attribute.name.attack_knockback&quot;, 0, 0, 5)
&lt;span class=&quot;err&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;data-generation&quot;&gt;Data generation&lt;/h3&gt;

&lt;p&gt;A recipe provider must now override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecipeGenerator&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generate&lt;/code&gt;. The new method takes the registries and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exporter&lt;/code&gt;, and returns a new instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RecipeGenerator&lt;/code&gt; that actually generates the recipes.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- public void generate(RecipeExporter exporter) {
-    offerPlanksRecipe2(exporter, SIMPLE_BLOCK, ItemTags.ACACIA_LOGS, 1);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ protected RecipeGenerator getRecipeGenerator(RegistryWrapper.WrapperLookup registries, RecipeExporter exporter) {
+    return new RecipeGenerator(registries, exporter) {
+        @Override
+        public void generate() {
+            offerPlanksRecipe2(SIMPLE_BLOCK, ItemTags.ACACIA_LOGS, 1);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;actionresult&quot;&gt;ActionResult&lt;/h3&gt;

&lt;p&gt;Previously, action results have been represented in several ways, including the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemActionResult&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedActionResult&lt;/code&gt; classes. In Minecraft 1.21.2, these classes have been merged into a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult&lt;/code&gt; class, which provides direct replacements for the previous methods for all three classes:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Old&lt;/th&gt;
      &lt;th&gt;New&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult.success(world.isClient())&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult.SUCCESS&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedActionResult.pass(stack)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult.PASS&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedActionResult.fail(stack)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult.FAIL&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedActionResult.success(stack, world.isClient())&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult.SUCCESS&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedActionResult.consume(stack)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult.CONSUME&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;If an action replaces the hand stack with another instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt;, then it should be marked with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult#withNewHandStack&lt;/code&gt; method. For example, an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item#use&lt;/code&gt; implementation that replaces the hand stack might be:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ActionResult&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;World&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PlayerEntity&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Hand&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;ItemStack&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStackInHand&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getCount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;ItemStack&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newStack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ItemStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Items&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BLAZE_ROD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ActionResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SUCCESS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withNewHandStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ActionResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PASS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the other hand, if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt; instance for the hand stack is the same as the one provided to an interaction method such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item#use&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult#withNewHandStack&lt;/code&gt; method should not be called.&lt;/p&gt;

&lt;p&gt;This change affects all places where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedActionResult&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemActionResult&lt;/code&gt; were previously used in Minecraft’s code. In Fabric API, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UseItemCallback&lt;/code&gt; event in the Events Interaction module now returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionResult&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedActionResult&amp;lt;ItemStack&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;item-components&quot;&gt;Item components&lt;/h3&gt;
&lt;p&gt;Because elytra behavior is now controlled by a new item component, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:glider&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricElytraItem&lt;/code&gt; was removed. Add the component to your elytra item instead.&lt;/p&gt;

&lt;h3 id=&quot;block-entities&quot;&gt;Block entities&lt;/h3&gt;

&lt;p&gt;In Minecraft 1.21.1 (released in August), a change was made that required mods to add all supported blocks to block entities. For example, a mod with a new sign block must add the block to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockEntityType#SIGN&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;BlockEntityType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SIGN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addSupportedBlock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ModBlocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TEAL_SIGN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In Minecraft 1.21.2, block entity types are no longer constructed using builders. Therefore, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBlockEntityType.Builder&lt;/code&gt; was removed, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBlockEntityTypeBuilder&lt;/code&gt; is no longer deprecated.&lt;/p&gt;

&lt;h3 id=&quot;registries&quot;&gt;Registries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Registry&lt;/code&gt; now implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryEntryLookup&lt;/code&gt;. This resulted in several name changes. To query a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryEntry&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&lt;/code&gt;, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOptional&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOrThrow&lt;/code&gt;. (Same applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryEntryList&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TagKey&lt;/code&gt;.) If you want to query the registry value, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getValueOrThrow&lt;/code&gt;. See the table below for all changes.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Old&lt;/th&gt;
      &lt;th&gt;New&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getEntry&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOptional&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entryOf&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOrThrow&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOrThrow&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getValueOrThrow&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOrEmpty&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOptionalValue&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getEntryList&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOptional&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Similarly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DynamicRegistryManager#get&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryWrapper.WrapperLookup#getWrapperOrThrow&lt;/code&gt; has been renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOrThrow&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOptionalWrapper&lt;/code&gt; was renamed tp &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getOptional&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;rendering&quot;&gt;Rendering&lt;/h3&gt;
&lt;h4 id=&quot;entity-rendering&quot;&gt;Entity rendering&lt;/h4&gt;
&lt;p&gt;Entity rendering has received a large refactor that decouples the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Entity&lt;/code&gt; instance from its respective rendering calls. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityRenderer&lt;/code&gt; now has an additional type parameter, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S extends EntityRenderState&lt;/code&gt;, which represents a ‘render state’, which is a mutable class containing only the parameters of the entity that are used in rendering.&lt;/p&gt;

&lt;p&gt;Previously, renderer methods accessed the entity instance directly. However, accessing entity information now happens in three steps.&lt;/p&gt;

&lt;p&gt;First, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityRenderer#createRenderState&lt;/code&gt; method is called to construct an instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt; for the given entity with placeholder values:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createRenderState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityRenderer#updateRenderState&lt;/code&gt; method performs the operation of copying information from the entity to its render state:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateRenderState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tickDelta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateRenderState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tickDelta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Example: entity has an 'is saddled' field&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isSaddled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isSaddled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityRenderer#render&lt;/code&gt; method (as well as other renderer methods) accesses information from the entity’s render state:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MatrixStack&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VertexConsumerProvider&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertexConsumers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertexConsumers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isSaddled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Render the saddle&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;shaders&quot;&gt;Shaders&lt;/h4&gt;
&lt;p&gt;In Fabric Rendering API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CoreShaderRegistrationCallback&lt;/code&gt; was removed. Vanilla resource pack now allows loading modded core shaders.&lt;/p&gt;

&lt;h4 id=&quot;other-changes&quot;&gt;Other changes&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WorldRenderer&lt;/code&gt; methods for rendering certain vertices (like a box) were transferred to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VertexRendering&lt;/code&gt;.&lt;/p&gt;

&lt;!-- TODO Shader changes. Models. --&gt;

&lt;h3 id=&quot;recipes&quot;&gt;Recipes&lt;/h3&gt;
&lt;p&gt;The recipe system was reworked. To summarize:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Recipes are now identified using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&amp;lt;? extends Recipe&amp;gt;&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Recipe&lt;/code&gt; and the recipe ID is now server-side only. It cannot be accessed from the client.&lt;/li&gt;
  &lt;li&gt;Instead, clients receive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RecipeDisplayEntry&lt;/code&gt;. It contains all information needed to display and run the recipe book. Recipes are identified using an integer (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NetworkRecipeId&lt;/code&gt;) on the client. A recipe can have multiple display entries.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IngredientPlacement&lt;/code&gt; controls the placement of ingredients on the crafting table, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RecipeMatcher&lt;/code&gt; handles recipe matching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ingredient&lt;/code&gt; is now internally a list of items, not item stacks.&lt;/p&gt;

&lt;p&gt;In Fabric API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomIngredientSerializer#getCodec&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowEmpty&lt;/code&gt; param removed, empty now always disallowed.&lt;/p&gt;

&lt;h3 id=&quot;biome&quot;&gt;Biome&lt;/h3&gt;

&lt;p&gt;Water cave carvers (which, before 1.18, were seen in seabeds) were removed, along with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GenerationStep.Carver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Fabric Biome API, biome modification methods like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addCarver&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;removeCarver&lt;/code&gt; no longer takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GenerationStep.Carver&lt;/code&gt; argument.&lt;/p&gt;

&lt;h3 id=&quot;profiler&quot;&gt;Profiler&lt;/h3&gt;
&lt;p&gt;The shared profiler is now accessed using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Profilers#get&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- world.getProfiler().push(&quot;tinyPotato&quot;);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ Profilers.get().push(&quot;tinyPotato&quot;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;loot-tables&quot;&gt;Loot tables&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootTables#EMPTY&lt;/code&gt; was removed. The game uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt; to mark the lack of loot tables.&lt;/p&gt;

&lt;p&gt;Some loot context-related logics are now shared with recipes, resulting in name changes. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootContextParameter&lt;/code&gt; is now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContextParameter&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootContextType&lt;/code&gt; is now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContextType&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;yarn-renames&quot;&gt;Yarn renames&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;This section only affects those using the Yarn mapping.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As part of regular Yarn maintainace, the following changes were made. These should be a simple replacement:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModelTransformationMode&lt;/code&gt; is transferred to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net.minecraft.item&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RealmsLoadingWidget&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoadingWidget&lt;/code&gt; and transferred to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client.gui.widget&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Several &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Brain&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Task&lt;/code&gt;-related names: see &lt;a href=&quot;https://github.com/FabricMC/yarn/pull/3992&quot;&gt;the pull request&lt;/a&gt; for details.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registryLookupFuture&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registriesFuture&lt;/code&gt; in several locations.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codecs#NONNEGATIVE_INT&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NON_NEGATIVE_INT&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QUATERNIONF&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VECTOR3F&lt;/code&gt; are renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QUATERNION_F&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VECTOR_3F&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Screen#initTabNavigation&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;refreshWidgetPositions&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMapImpl&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MergedComponentMap&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContainerComponentModifier#create&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack#encode&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toNbt&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">Minecraft 1.21.2, the “Bundles of Bravery” drop, is expected to release soon. Mojang has recently announced that they will release these “drops” throughout the year. Like with other updates, this drop contains some significant changes affecting mod makers.</summary></entry><entry><title type="html">Fabric for Minecraft 1.21 &amp;amp; 1.21.1</title><link href="https://fabricmc.net/2024/05/31/121.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.21 &amp;amp; 1.21.1" /><published>2024-05-31T00:00:00+00:00</published><updated>2024-05-31T00:00:00+00:00</updated><id>https://fabricmc.net/2024/05/31/121</id><content type="html" xml:base="https://fabricmc.net/2024/05/31/121.html">&lt;p&gt;Minecraft 1.21 is expected to be released on June 13, with some significant changes affecting mod makers.&lt;/p&gt;

&lt;p&gt;It’s been only a month and a half since we last released a blogpost. Yet, this update is nothing small - some changes are likely to affect most, if not all, mods.&lt;/p&gt;

&lt;p&gt;As always, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version.&lt;/strong&gt; We ask everyone kindly not to pester them. &lt;strong&gt;We also recommend all players to make a backup of their worlds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;
&lt;p&gt;Developers should use Loom 1.6 (at the time of writing) to develop mods for Minecraft 1.21. Players should install the latest stable version of Fabric Loader (currently 0.15.11).&lt;/p&gt;
&lt;h3 id=&quot;new-fabric-api-changes&quot;&gt;New Fabric API changes&lt;/h3&gt;
&lt;p&gt;With the help of many contributors, Fabric API has received some new features since the last update blog post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Conventional Tags: Default English Translations for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt; namespaced tags (TelepathicGrunt)&lt;/li&gt;
  &lt;li&gt;Data Generation: Support extending dynamic registries in datagen (SquidDev)&lt;/li&gt;
  &lt;li&gt;Item API: Add API to modify default item components (modmuss50)&lt;/li&gt;
  &lt;li&gt;Resource Conditions: Support loading a single resource condition instead of array (Apollo)&lt;/li&gt;
  &lt;li&gt;Resource Conditions: Registry resource conditions (SquidDev)&lt;/li&gt;
  &lt;li&gt;Removed Herobrine (Tiny Potato)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;tag-translation&quot;&gt;Tag translation&lt;/h4&gt;
&lt;p&gt;Mods are now strongly encouraged to provide an English translation for item tags it provides. For example, the translation for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test:potatoes&lt;/code&gt; should be declared like this:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tag.item.test.potatoes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Potatoes&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although these are not used by the API itself, other mods (such as recipe viewers) rely on them for proper display.&lt;/p&gt;

&lt;h3 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Note: breaking changes related to vanilla changes are addressed separately below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One deprecated module was removed: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-models-v0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Item API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EquipmentSlotProvider#getPreferredEquipmentSlot&lt;/code&gt; is now passed a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LivingEntity&lt;/code&gt;. Implementations are expected to check themselves whether the slot is available, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entity.canUseSlot(EquipmentSlot)&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricItem#getAttributeModifiers&lt;/code&gt; was removed; use Default Components API instead.&lt;/p&gt;

&lt;p&gt;Registry Sync now freezes the registry at an earlier point. This does not affect mods that register things in their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModInitializer&lt;/code&gt;s, but might affect more complex mods. Make sure to register everything during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModInitializer&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;
&lt;p&gt;This version brought many breaking changes, including data-driven Enchantments. Data pack structures also changed, using singular nouns (instead of plurals) in many places.&lt;/p&gt;

&lt;h3 id=&quot;identifier&quot;&gt;Identifier&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt; constructor is now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protected&lt;/code&gt;. Use the static method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;of&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ofVanilla&lt;/code&gt; to construct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt;. Replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new Identifier&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier.of&lt;/code&gt; using text editors or IDEs should be sufficient.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- var id = new Identifier(&quot;example&quot;, &quot;foo_bar&quot;);
- var id2 = new Identifier(&quot;test:single_argument&quot;);
- var creeper = new Identifier(&quot;minecraft&quot;, &quot;creeper&quot;);
- @Nullable var customId = Identifier.of(&quot;namespace&quot;, unsanitizedInput);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ var id = Identifier.of(&quot;example&quot;, &quot;foo_bar&quot;);
+ var id2 = Identifier.of(&quot;test:single_argument&quot;);
+ var creeper = Identifier.ofVanilla(&quot;creeper&quot;); // very slightly improved performance
+ @Nullable var customId = Identifier.tryParse(&quot;namespace&quot;, unsanitizedInput);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pro tip: make a method to construct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt; for your mod’s namespace; this can be imported later using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import static&lt;/code&gt; to shorten your code.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mod_namespace&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;enchantments&quot;&gt;Enchantments&lt;/h3&gt;
&lt;p&gt;Enchantments are now data-driven. This means that they are no longer hardcoded - instead, they’re part of data packs. Consequentially, there are several important changes in how mods handle enchantments.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Generally, enchantments either “do something” (like causing an explosion), or “modify a value” (like attack damage).
Example: Instead of checking if the player has Thorns and applying damage to the attacker, a mod should now call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentHelper#onTargetDamaged&lt;/code&gt; which should automatically handle this.
Example 2: Instead of checking the level of Knockback, a mod should now call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentHelper#modifyKnockback&lt;/code&gt; with the original knockback.&lt;/li&gt;
  &lt;li&gt;Sometimes, a code needs to check if an item has certain enchantments. Because enchantments are no longer hard-coded, this is done using enchantment tags.
Example 3: Breaking a beehive with Silk Touch prevents bees from getting released. Previously, this was done by checking for the Silk Touch enchantment. Now, this is done by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentHelper#hasAnyEnchantmentsIn(stack, EnchantmentTags#PREVENTS_BEE_SPAWNS_WHEN_MINING)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;enchantment-code-structures&quot;&gt;Enchantment Code Structures&lt;/h3&gt;
&lt;p&gt;An &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enchantment&lt;/code&gt; is, well, an enchantment. Because it is now defined by a dynamic registry, it is often handled as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryEntry&amp;lt;Enchantment&amp;gt;&lt;/code&gt;. These can be obtained from the dynamic registry, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;world.getRegistryManager()&lt;/code&gt; or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registryLookup&lt;/code&gt; passed to various methods.&lt;/p&gt;

&lt;p&gt;An enchantment has effect components, which is a map of effect types to list of effects. Effect types are pre-defined keys that enchantments can define behaviors for. For example, an enchantment may want to add “multiply by 2” behavior for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DAMAGE&lt;/code&gt; effect type, or “explode” behavior for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST_ATTACK&lt;/code&gt; effect type. These are defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentEffectComponentTypes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The values of effect components are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentEffectEntry&lt;/code&gt;. This is a pair of the effect and an optional condition. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootCondition&lt;/code&gt; is reused for this purpose.&lt;/p&gt;

&lt;p&gt;Enchantment effects can be categorized into three categories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentValueEffect&lt;/code&gt;. When given a value, the effect calculates the modified value. Examples include Protection (which modifies &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DAMAGE_PROTECTION&lt;/code&gt;), Lure (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FISHING_LUCK_BONUS&lt;/code&gt;), Unbreaking (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITEM_DAMAGE&lt;/code&gt;), and Multishot (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROJECTILE_COUNT&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentEntityEffect&lt;/code&gt;. This effect does something when triggered. Examples include Thorns and Channeling (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST_ATTACK&lt;/code&gt;) and Flame (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROJECTILE_SPAWNED&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeEnchantmentEffect&lt;/code&gt;, which adds an attribute to the entity. Unlike entity effects, attributes persist until the enchantment becomes inapplicable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentLocationBasedEffect&lt;/code&gt; is an interface implemented by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentEntityEffect&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AttributeEnchantmentEffect&lt;/code&gt;. In addition, some enchantment effect types simply require effective values to be specified directly - like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CROSSBOW_CHARGING_SOUNDS&lt;/code&gt;, which is a list of sounds. Some effects, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PREVENT_ARMOR_CHANGE&lt;/code&gt;, cannot be configured further.&lt;/p&gt;

&lt;h3 id=&quot;using-vanilla-enchantments&quot;&gt;Using Vanilla Enchantments&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentHelper&lt;/code&gt; methods can be used to handle vanilla enchantments.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Example of modifying a value&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newDamage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EnchantmentHelper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDamage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;attackTarget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;damageSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;baseDamage&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// For values with no base value (such as Protection)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;protection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EnchantmentHelper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getProtectionAmount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;damageSource&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Entity-based effect&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;EnchantmentHelper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onTargetDamaged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;attackTarget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;damageSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;weapon&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Checking if an ItemStack is enchanted with certain enchantments&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;EnchantmentHelper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hasAnyEnchantmentsIn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;EnchantmentTags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PREVENTS_BEE_SPAWNS_WHEN_MINING&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Checking for nonconfigurable effects&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// e.g. checking for Curse of Binding&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;EnchantmentHelper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hasAnyEnchantmentsWith&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;EnchantmentEffectComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PREVENT_ARMOR_CHANGE&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;adding-a-new-enchantment&quot;&gt;Adding a new Enchantment&lt;/h3&gt;
&lt;p&gt;Adding a new enchantment is now done by writing JSON files. You can use Data Generation to generate enchantments easily.&lt;/p&gt;

&lt;p&gt;An enchantment can perform many tasks, like applying attributes, replacing blocks or summoning an entity. However, not all things are possible. To add a custom &lt;strong&gt;effect type&lt;/strong&gt;, a new effect class must be created and its codec registered. &lt;strong&gt;An effect type must exist in both the client and the server.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enchantment tags are used to specify exclusive enchantments (e.g. Fortune and Silk Touch) and where the enchantments can be obtained. Make sure to add your enchantments to those tags.&lt;/p&gt;

&lt;h3 id=&quot;enchantment-related-fabric-api-changes&quot;&gt;Enchantment-related Fabric API changes&lt;/h3&gt;
&lt;p&gt;The following event callbacks now pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryEntry&amp;lt;Enchantment&amp;gt;&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enchantment&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentEvents.AllowEnchanting#allowEnchanting&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricItem#canBeEnchantedWith&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricItemStack#canBeEnchantedWith&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentContext&lt;/code&gt; was reworked. Previously, a context was one of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RANDOM_ENCHANTMENT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ANVIL&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENCHANT_COMMAND&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOOT_RANDOM_ENCHANTMENT&lt;/code&gt;. To clarify its purpose, they are now one of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ACCEPTABLE&lt;/code&gt; (e.g. anvils) or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PRIMARY&lt;/code&gt; (e.g. enchanting tables). For example, a helmet can be enchanted with Thorns using anvils but not in enchanting tables, because only chestplates are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PRIMARY&lt;/code&gt; in case of Thorns.&lt;/p&gt;

&lt;h3 id=&quot;teleportation&quot;&gt;Teleportation&lt;/h3&gt;
&lt;p&gt;Both intra-dimensional and cross-dimensional teleportation can now be performed using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Entity#teleportTo&lt;/code&gt; (previously known as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;moveToWorld&lt;/code&gt;). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TeleportTarget&lt;/code&gt; now contains the destination world and position.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricDimensions&lt;/code&gt; was removed, because its only API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;teleport&lt;/code&gt;, is effectively superseded with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Entity#teleportTo&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;data-pack-paths&quot;&gt;Data Pack Paths&lt;/h3&gt;
&lt;p&gt;Data packs now use singular nouns in the following paths:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tag subdirectories such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tags/blocks&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tags/entity_types&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tags/functions&lt;/code&gt;. They are now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tags/block&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tags/entity_type&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tags/function&lt;/code&gt;, respectively. &lt;strong&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tags&lt;/code&gt; directory itself remains plural.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Advancements (previously &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;advancements&lt;/code&gt;, now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;advancement&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Functions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;functions&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Item modifiers/loot functions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;item_modifiers&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;item_modifier&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Loot tables (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loot_tables&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loot_table&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Predicates/loot conditions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;predicates&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;predicate&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Recipes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipes&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipe&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Structures (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;structures&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;structure&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Fabric API news, GameTest structure directories are now singular as well; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gametest/structures&lt;/code&gt;, they are now placed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gametest/structure&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;rendering-changes&quot;&gt;Rendering Changes&lt;/h3&gt;
&lt;p&gt;In the Fabric Rendering API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HudRenderCallback&lt;/code&gt; now passes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RenderTickCounter&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tickDelta&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tickDelta&lt;/code&gt; can be obtained from the counter. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WorldRenderContext&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tickDelta&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;limitTime&lt;/code&gt; methods are also replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tickCounter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are some other, significant internal refactors to rendering. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BufferBuilder#next()&lt;/code&gt; was removed, and the methods for beginning or ending the building process has changed:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- BufferBuilder builder = tessellator.getBuffer();
- builder.begin(...);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ BufferBuilder builder = tessellator.begin(...);
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;- builder.vertex(...).texture(...).color(...).next();
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ builder.vertex(...).texture(...).color(...)
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;- tessellator.draw();
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ BufferRenderer.drawWithGlobalProgram(builder.end());
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;miscellaneous&quot;&gt;Miscellaneous&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricCodecProvider&lt;/code&gt; now has a new constructor that takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&lt;/code&gt; instead of directory name. This can be used with, for example, item modifier providers. The old constructor can still be used for non-registered codecs.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">Minecraft 1.21 is expected to be released on June 13, with some significant changes affecting mod makers.</summary></entry><entry><title type="html">Fabric for Minecraft 1.20.5 &amp;amp; 1.20.6</title><link href="https://fabricmc.net/2024/04/19/1205.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.20.5 &amp;amp; 1.20.6" /><published>2024-04-19T00:00:00+00:00</published><updated>2024-04-19T00:00:00+00:00</updated><id>https://fabricmc.net/2024/04/19/1205</id><content type="html" xml:base="https://fabricmc.net/2024/04/19/1205.html">&lt;p&gt;Minecraft 1.20.5 is to be released in the near future with significant changes affecting mod makers.&lt;/p&gt;

&lt;p&gt;But first, we need to make this clear: &lt;strong&gt;1.20.5 is a record-breaking update.&lt;/strong&gt; This development cycle spans from December 18, 2023 to April of 2024, the longest for any “dot release”. We saw 15 snapshots, the first time it became two digits for a dot release (previous record was 1.20.3 for 8 snapshots). And no surprise: the amount of changes is also unprecedented.&lt;/p&gt;

&lt;p&gt;For this reason, &lt;strong&gt;we ask all players to be patient, and give mod developers time to update to this new version.&lt;/strong&gt; We ask everyone kindly not to pester them. 1.20.5 is expected to be the last update of the 1.20 series.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We recommend all players to make a backup of the world.&lt;/strong&gt; For content mod users, creating a new world is recommended, as most mods do not handle world data upgrades of this magnitude.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;java-21&quot;&gt;Java 21&lt;/h2&gt;
&lt;p&gt;Minecraft 1.20.5 now requires Java 21 to run. This means mods can be compiled for Java 21 and use the latest features. This also marks the end of 32-bit support.&lt;/p&gt;

&lt;p&gt;To set up a development environment you will need to use Java 21, Loom 1.6, and Gradle 8.6 or higher.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;
&lt;p&gt;Developers should use Loom 1.6 (at the time of writing) to develop mods for Minecraft 1.20.5. Players should install the latest stable version of Fabric Loader (currently 0.15.10).&lt;/p&gt;

&lt;h3 id=&quot;loom-15--16&quot;&gt;Loom 1.5 &amp;amp; 1.6&lt;/h3&gt;
&lt;p&gt;There has been two major updates to Loom since the last blogpost: 1.5 and 1.6.&lt;/p&gt;

&lt;p&gt;Loom 1.5 includes several performance boosts and small bug fixes. Notably, the mixins can now be remapped using the Tiny Remapper instead of Mixin annotation processor. When enabled, the mixins are remapped in-place and the output jar no longer contains a refmap. This is currently experimental and opt-in.&lt;/p&gt;

&lt;p&gt;Loom 1.6 also brought more performance improvements. Decompiler caches were added, meaning that changes to access wideners no longer cause the entire game to be decompiled. There is also an update to how Loom handles existing locks (such as when two Gradle runs occur simultaneously) - it will no longer clear the cache, instead waiting for one process to exit. The error message for locked files is now more detailed, as well.&lt;/p&gt;

&lt;p&gt;Please see the &lt;a href=&quot;https://github.com/FabricMC/fabric-loom/releases/tag/1.5&quot;&gt;Loom 1.5&lt;/a&gt; and &lt;a href=&quot;https://github.com/FabricMC/fabric-loom/releases/tag/1.6&quot;&gt;Loom 1.6&lt;/a&gt; release notes for all of the changes.&lt;/p&gt;

&lt;h3 id=&quot;localization&quot;&gt;Localization&lt;/h3&gt;
&lt;p&gt;Fabric has recently moved to using Crowdin to help manage translations for our projects. This makes it much easier to contribute translations across all Fabric projects.&lt;/p&gt;

&lt;p&gt;Current projects include Fabric API and installer. &lt;!-- Docs are WIP --&gt; If you are able to help translate Fabric into your language, please visit &lt;a href=&quot;https://crowdin.com/project/fabricmc&quot;&gt;the Crowdin website&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;new-fabric-api-changes&quot;&gt;New Fabric API changes&lt;/h3&gt;
&lt;p&gt;With the help of many contributors, Fabric API has received some new features since the last update blog post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;New API: Data Attachments. This allows attaching custom data to block entities, chunks, entites, and worlds. Attached data can be saved or persisted between mob conversions. (Syst3ms)&lt;/li&gt;
  &lt;li&gt;Interaction Events: add client after block break event (kevinthegreat1)&lt;/li&gt;
  &lt;li&gt;GameTest API: add a system property for a custom output directory for gametest structures (ErrorCraft)&lt;/li&gt;
  &lt;li&gt;Entity Events: add mob conversion event (Syst3ms)&lt;/li&gt;
  &lt;li&gt;Fabric Rendering: add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AtlasSourceTypeRegistry&lt;/code&gt; (PepperCode1)&lt;/li&gt;
  &lt;li&gt;Data Generation: add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricCodecDataProvider&lt;/code&gt; (ErrorCraft)&lt;/li&gt;
  &lt;li&gt;Resource Loader: significant refactors to support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pack.mcmeta&lt;/code&gt; metadata like filters and overlays. (apple502j)&lt;/li&gt;
  &lt;li&gt;Fabric Rendering: add support for custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ColorResolver&lt;/code&gt;s (PepperCode1)&lt;/li&gt;
  &lt;li&gt;Fluids Rendering: expose a function for querying the non-default fluid renderer (jellysquid3)&lt;/li&gt;
  &lt;li&gt;Lifecycle Events: add save events to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerLifecycleEvents&lt;/code&gt; (MrNavaStar)&lt;/li&gt;
  &lt;li&gt;Item API: add enchantments API (Syst3ms)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is one more addition for advanced developers: you can now declare Fabric API as a dependency using BOM or version catalogs. Check &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/3487&quot;&gt;the pull request&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h3 id=&quot;breaking-changes-and-deprecations&quot;&gt;Breaking changes and deprecations&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Note: breaking changes related to vanilla changes are discussed below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The following APIs were removed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-containers-v0&lt;/code&gt; (previously deprecated)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-events-lifecycle-v0&lt;/code&gt; (previously deprecated)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric-mining-level-api-v1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ScreenRegistry&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ScreenHandlerRegistry&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModifyItemAttributeModifiersCallback&lt;/code&gt; from the Item API was removed without replacement due to code changes making it infeasible to port.&lt;/p&gt;

&lt;p&gt;In Object Builder API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricItemSettings&lt;/code&gt; was removed. Use vanilla &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item.Settings&lt;/code&gt; instead; interface injection provides settings added by Fabric API. Similarly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBlockSettings&lt;/code&gt; was deprecated and replaced with vanilla &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AbstractBlock.Settings&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricEntityTypeBuilder&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBlockEntityTypeBuilder&lt;/code&gt; were also deprecated; use vanilla builders instead.&lt;/p&gt;

&lt;h3 id=&quot;codec-based-resource-conditions&quot;&gt;Codec-based Resource Conditions&lt;/h3&gt;
&lt;p&gt;Unrelated to the 1.20.5 update, a significant change was made to Resource Conditions’ internal workings. This update was developed by Apollo and apple502j. The only breaking change to the JSON syntax is the removal of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(block/item/fluid)_tags_populated&lt;/code&gt; conditions, but data generation is heavily affected.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConditionJsonProvider&lt;/code&gt; interface has been removed and been replaced by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceCondition&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceCondition&lt;/code&gt; has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; method, for determining whether the condition should pass, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getType&lt;/code&gt;, which returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceConditionType&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;withConditions&lt;/code&gt; methods in data providers now take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceCondition&lt;/code&gt; instances. Methods in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultResourceConditions&lt;/code&gt; that created conditions have been moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceConditions&lt;/code&gt;. A custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceConditionType&lt;/code&gt; should be registered with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceConditions#register&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In addition, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabric:true&lt;/code&gt; condition was added. This condition always passes.&lt;/p&gt;

&lt;h3 id=&quot;convention-tag-unification&quot;&gt;Convention Tag unification&lt;/h3&gt;
&lt;p&gt;Another significant change was made in the Convention Tags. As part of collaborative efforts with NeoForge, TelepathicGrunt has prepared (and we released) the version 2 of the tags. Version 1 is now deprecated.&lt;/p&gt;

&lt;p&gt;As the changes are too long to list here, developers are encouraged to check the &lt;a href=&quot;https://github.com/FabricMC/fabric/pull/3310&quot;&gt;pull request&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;
&lt;p&gt;In short, these are the veeery major changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Item Components. Item stacks no longer use NBT as runtime data storage, instead using predefined “components” to keep values like custom name, enchantments, or damage.&lt;/li&gt;
  &lt;li&gt;Networking. Instead of manually processing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;, packets are now serialized using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt;s. In Fabric Networking API, the previous &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;-based APIs were removed; the newer, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricPacket&lt;/code&gt;-based API was rewritten to make use of the vanilla &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomPayload&lt;/code&gt; interface.&lt;/li&gt;
  &lt;li&gt;Registries. Likely as a preparation for data-driven blocks and items, serialization/deserialization of most objects now require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryWrapper.WrapperLookup&lt;/code&gt; instance. This is most noticeable in texts and data generation. In addition, loot tables are now managed by a new type of registry called “reloadable registries”.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;item-components&quot;&gt;Item Components&lt;/h3&gt;
&lt;p&gt;We skip the general description of the item components system, which you can check in the slicedlime’s video: &lt;a href=&quot;https://www.youtube.com/watch?v=iY9OHAd4Aco&quot;&gt;News in Data Pack Version 33 (24w09a): Item Components!&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we begin the journey into the implementation of item components:&lt;/p&gt;

&lt;p&gt;There are five main objects in the item components:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataComponentType&lt;/code&gt;, a type of components, serving as keys;&lt;/li&gt;
  &lt;li&gt;Component classes (can be any object), serving as values;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMap&lt;/code&gt;, a read-only view of components;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMapImpl&lt;/code&gt;, which is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMap&lt;/code&gt; that can be modified, and internally a pair of unmodifiable base &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMap&lt;/code&gt; and the “overrides” that are modified; and&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentChanges&lt;/code&gt;, a map of component type to the changes for the value (either setting it to a specific value or removing it). This can be used as a diff applied to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt;; you apply an instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentChanges&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMapImpl&lt;/code&gt;, so that the overrides part of the map reflects the changes. In other parts of the code, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentChanges&lt;/code&gt; is just used as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMapImpl&lt;/code&gt; minus the base.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, how does this work?&lt;/p&gt;

&lt;p&gt;Each item has the base components. In addition to the base components common to all items, like having empty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentsComponent&lt;/code&gt;, some items provide additional base components. A notable example is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataComponentTypes#DAMAGE&lt;/code&gt; for armors, tools, and weapons. A component type that exists in the base has a corresponding default value; here the default damage is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt; can either 1) add an additional component not present in the base; 2) change the components from the one in the base; or 3) remove a component that exists in the base. The final components of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt;, obtainable as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentMap&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack#getComponents&lt;/code&gt;, reflects all three.&lt;/p&gt;

&lt;h4 id=&quot;using-item-components&quot;&gt;Using Item Components&lt;/h4&gt;

&lt;p&gt;Item components on item stacks have a similar API surface to a map. Here are some common operations that can be done, using the example of an item’s custom name (note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Text&lt;/code&gt; is directly used as the component value):&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Similar to Map#get&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Similar to Map#put&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Returns the previous value, if any&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Lorem ipsum&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Similar to Map#getOrDefault&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrDefault&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Similar to Map#remove&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removedName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Similar to Map#compute&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// In this example, we change the color of the item name&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// (Note: stack#getName already checks for custom name, so in reality this does not need apply() call.)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;formatted&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Formatting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;RED&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Getting/setting the custom data (NBT). This is useful for datapack makers and server-side modders, because custom item components (see below) need to be synced to the clients, while custom data remains an unparsed NBT.&lt;/p&gt;

&lt;p&gt;Unlike the previous example, this uses a component record &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NbtComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note: &lt;strong&gt;component values are supposed to be immutable&lt;/strong&gt; - even if you can modify it, don’t. Always copy and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set()&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;NbtCompound&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;NbtComponent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;component&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NbtComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Setting&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_DATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Getting a copy&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_DATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;NbtCompound&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;copyNbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Using NbtComponent#apply, which copies automatically, to modify the NBT&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Note: you might want to use the static method NbtComponent#set instead,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// which makes this a bit shorter&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_DATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NbtComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DEFAULT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentNbt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;currentNbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;putInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Checking if a certain NBT is a subset of the stack NBT&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// (also known as: &quot;non-strict matching&quot;)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;NbtCompound&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requiredNbt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrDefault&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_DATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NbtComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DEFAULT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requiredNbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// use createPredicate to make Predicate&amp;lt;ItemStack&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentChanges&lt;/code&gt; to mass-modify the components of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// stack is a damageable item.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Repair the item and remove custom name.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Note that the resulting stack has no components because 0 damage is the default from the base components.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;changes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ComponentChanges&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DAMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;applyChanges&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;changes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Making an item with base components:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DataComponentTypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CUSTOM_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)));&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Call #component multiple times for multiple base components.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Note: calling maxDamage automatically adds DAMAGE component.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Making a custom component. Note that like many registered entries, these must be present in both the client and the server.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DataComponentType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;WEIRDNESS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DataComponentType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;packetCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;VAR_INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// in the initializer&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Registry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Registries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DATA_COMPONENT_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;weirdness&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;WEIRDNESS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;some-caveats&quot;&gt;Some caveats&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Component values should not be modified directly. Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Record&lt;/code&gt; or other immutable object is highly recommended. Always copy, modify, then set.&lt;/li&gt;
  &lt;li&gt;Setting an invalid value for a component does not cause an error immediately, but will lead to a crash during save, and possible data corruption. A common example is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NONNEGATIVE_INT&lt;/code&gt; being used for an incrementing value; when it overflows and the value is set to negatives, saving it would crash.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;blockentity-interaction-with-components&quot;&gt;BlockEntity interaction with components&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockEntity&lt;/code&gt; stores the components when placing a block item stack with components and when pick-blocking. Components are not currently used to serialize block entities themselves. A block entity that uses components, like custom containers, should override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addComponents&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readComponents&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;removeFromCopiedStackNbt&lt;/code&gt; methods:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addComponents&lt;/code&gt; adds the block entity’s stored data to a component builder.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readComponents&lt;/code&gt; reads the block entity data from components.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;removeFromCopiedStackNbt&lt;/code&gt; removes NBT keys which are now serialized using components when in item stacks. For example, a chest’s held stacks are stored under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Items&lt;/code&gt; key when the block entity itself is serialized, and stored under a component when an item stack for the block entity is serialized. To prevent double serialization, this method removes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Items&lt;/code&gt; from the item stack NBT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootableContainerBlockEntity&lt;/code&gt; handles component changes themselves, so you do not have to reinvent the wheel if you use them.&lt;/p&gt;

&lt;h3 id=&quot;item-component-related-fabric-api-changes&quot;&gt;Item Component-related Fabric API changes&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowNbtUpdateAnimations&lt;/code&gt; method of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricItem&lt;/code&gt; was renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowComponentsUpdateAnimations&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricItem.getAttributeModifiers&lt;/code&gt; changes?
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isSuitableFor&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getFoodComponents&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricItemStack&lt;/code&gt; removed/replaced with vanilla components.&lt;/p&gt;

&lt;h4 id=&quot;recipe-api&quot;&gt;Recipe API&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultCustomIngredients#nbt&lt;/code&gt; and support for NBT ingredients were removed, as the game no longer uses NBT to store item stack-specific data.&lt;/p&gt;

&lt;p&gt;To check for custom name, enchantments, etc that were previously kept inside the NBT but are now recorded in the components (see below for details), use the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;components&lt;/code&gt; ingredient. To check for custom data component (a NBT data not used by the game but can be used by data packs or commands), use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;customData&lt;/code&gt; ingredient.&lt;/p&gt;

&lt;h4 id=&quot;transfer-api&quot;&gt;Transfer API&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransferVariant&lt;/code&gt; (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FluidVariant&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemVariant&lt;/code&gt;) is now a pair of the object and the components, instead of the object and NBT. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getNbt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hasNbt&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nbtMatches&lt;/code&gt; methods were replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getComponents&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hasComponents&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;componentsMatch&lt;/code&gt; methods. The following methods were removed: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyNbt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyOrCreateNbt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toNbt&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toPacket&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FluidVariant#of&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemVariant#of&lt;/code&gt; now takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComponentChanges&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Nullable NbtCompound&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransferVariant&lt;/code&gt; is now serialized using codecs and packet codecs. Therefore, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fromNbt&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fromPacket&lt;/code&gt; static methods were removed.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SingleVariantStorage#writeNbt&lt;/code&gt; instance method was removed; subclasses now provide separate methods named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;writeNbt&lt;/code&gt;. Both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readNbt&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;writeNbt&lt;/code&gt; now require passing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryWrapper.WrapperLookup&lt;/code&gt; instance; they should be available in the methods from which they are called (or you can use the world’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DynamicRegistryManager&lt;/code&gt; instance).&lt;/p&gt;

&lt;h3 id=&quot;other-item-changes&quot;&gt;Other Item changes&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;As noted in the video, an empty item stack is now serialized as omitting the field or an empty object. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack#fromNbt&lt;/code&gt; now returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&amp;lt;ItemStack&amp;gt;&lt;/code&gt; while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fromNbtOrEmpty&lt;/code&gt; supports empty NBT object. Both now require passing the registries. These methods log an error when an item with ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minecraft:air&lt;/code&gt; is encountered.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;writeNbt&lt;/code&gt; method was renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encode&lt;/code&gt;. The one with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NbtCompound&lt;/code&gt; argument allows adding to the existing compound, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;writeNbt&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The methods in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt; that reference &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Nbt&lt;/code&gt; are generally renamed to reference &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Components&lt;/code&gt; instead.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item#isNbtSynced&lt;/code&gt; was removed, specify custom packet codecs instead.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item#getBreakSound&lt;/code&gt; was added.&lt;/li&gt;
  &lt;li&gt;Attack damage and mining speed of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MiningToolItem&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwordItem&lt;/code&gt; are now specified in item settings via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attributeModifiers&lt;/code&gt; setting.&lt;/li&gt;
  &lt;li&gt;Item tooltips are now given a “tooltip type”, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TooltipContext&lt;/code&gt; is now under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemTooltipCallback&lt;/code&gt; Fabric API event now passes the type as well. Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hide_tooltip&lt;/code&gt; item component prevents the event from being invoked.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;item-damages&quot;&gt;Item damages&lt;/h4&gt;
&lt;p&gt;When damaging an item stack held in the hands or in the armor slots, you now pass the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EquipmentSlot&lt;/code&gt; instead of a callback:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- stack.damage(1, entity, p -&amp;gt; p.sendToolBreakStatus(Hand.MAIN_HAND));
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ stack.damage(1, entity, EquipmentSlot.MAINHAND);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When damaging an item stack held by non-entities (like shears in dispensers), the stack must be broken by the newly passed callback, not by checking the return value.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- if (stack.damage(1, random, null)) stack.setCount(0);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ stack.damage(1, random, null, () -&amp;gt; stack.setCount(0));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In Fabric API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomDamageHandler&lt;/code&gt; callback’s signature was changed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack stack, int amount, LivingEntity entity, Consumer breakCallback&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack stack, int amount, LivingEntity entity, EquipmentSlot slot, Runnable breakCallback&lt;/code&gt;. Additionally, calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;breakCallback&lt;/code&gt; now ignores the return value and vanilla damage handler (as the item is already broken).&lt;/p&gt;

&lt;h3 id=&quot;networking&quot;&gt;Networking&lt;/h3&gt;
&lt;p&gt;Previously, networking code was simple: reading from, and writing to, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;. Although this method still works, Mojang has added an abstraction layor: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt; works like the DataFixerUpper codecs used in JSON/NBT serialization - although they are not compatible with each other. To keep it simple, &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt; is a pair of deserializers and serializers&lt;/strong&gt; - or, decoders and encoders. This change reduces bugs related to wrong read/write order - which is one of the most difficult bugs to identify.&lt;/p&gt;

&lt;h4 id=&quot;how-to-create-a-packetcodec&quot;&gt;How to create a PacketCodec&lt;/h4&gt;
&lt;p&gt;Note: A new subclass of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;, &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryByteBuf&lt;/code&gt;, is used for PLAY-phase networking&lt;/strong&gt; (the one you’re probably using). For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfigurationNetworking&lt;/code&gt;, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryByteBuf&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt;s are usually stored in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public static final&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;Suppose we are serializing this record:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;VirtualHugs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Note: replaced PacketByteBuf with RegistryByteBuf&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;VirtualHugs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryByteBuf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readVarInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Instance method&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryByteBuf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;writeVarInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Static method, buffer-first&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryByteBuf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VirtualHugs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hugs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;writeVarInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hugs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The easy method - adopting existing code&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryByteBuf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VirtualHugs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PACKET_CODEC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Or, using static method:&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;PACKET_CODEC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ofStatic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The new method - building codecs from other codecs, like in DataFixerUpper&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// &quot;tuple&quot; is an ordered, un-keyed set of stuff.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Up to 3 fields can be serialized with vanilla method.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// The constructor always comes last.&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;CODEC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;VAR_INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Or, since there is only one field in VirtualHugs, this works too.&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;CODEC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;VAR_INT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;xmap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;VirtualHugs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;You might see some nasty casting errors in some cases. Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cast()&lt;/code&gt; on the codec to make it go away;&lt;/strong&gt; it’s generally safe to do so.&lt;/p&gt;

&lt;h4 id=&quot;advanced-packetcodecs-examples&quot;&gt;Advanced PacketCodecs examples&lt;/h4&gt;
&lt;p&gt;Here are some more examples:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// For a singleton (like an empty packet). Encoding something other than INSTANCE will error.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// It does not actually touch the buffer.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;singleton&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;INSTANCE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Using PacketCodec from classic API&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TextCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;TextCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Codec for Optional&amp;lt;Text&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Compatible with PacketByteBuf#readOptional&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;optText&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TextCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;PacketCodecs:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Codec for List&amp;lt;String&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// or Set&amp;lt;String&amp;gt;, each max 16 chars&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// both work fine, compatible with PacketByteBuf#readCollection&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stringSet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toCollection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;HashSet:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stringSet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;HashSet:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Map&amp;lt;String, BlockPos&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;positions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;HashMap:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlockPos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// What? DataFixerUpper codecs?&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Nah, these are just serialized as NBTs.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;advancement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Advancement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Serializing NbtCompound&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NBT_COMPOUND&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Serializing a registry value (by raw ID)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Note: these require RegistryByteBuf!&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryByteBuf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registryValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ITEM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Or, RegistryEntry&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryByteBuf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Biome&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;biome&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registryEntry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BIOME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Serializing an Enum&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodecs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;indexed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Direction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;VALUES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Direction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;fabric-networking-api&quot;&gt;Fabric Networking API&lt;/h4&gt;
&lt;p&gt;Networking API no longer directly uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;, except in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoginNetworking&lt;/code&gt;. Instead, you need to subclass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomPayload&lt;/code&gt; and register it. Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomPayload&lt;/code&gt; is a vanilla interface. While this is similar to the packet object-based networking introduced recently, it is different in some ways. (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketType&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricPacket&lt;/code&gt; were, therefore, removed.)&lt;/p&gt;

&lt;p&gt;Compare the following, pre-snapshot packet:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slapped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FabricPacket&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;SlapPacket:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PacketByteBuf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readUuid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PacketByteBuf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;writeUuid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slapped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And a new one:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slapped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomPayload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomPayload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PACKET_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomPayload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Identifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...));&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PacketCodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RegistryByteBuf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PACKET_CODEC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Uuids&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;xmap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;SlapPacket:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;SlapPacket:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slapped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are three differences you will notice:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Instead of now-removed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricPacket&lt;/code&gt;, we implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomPayload&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomPayload&lt;/code&gt; implementation has its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomPayload.Id&lt;/code&gt;. Unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketType&lt;/code&gt;, it lacks reference to the decoder.&lt;/li&gt;
  &lt;li&gt;The latter does not have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; method or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;-taking constructor. Instead, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PACKET_CODEC&lt;/code&gt; field was added. (Note, you can make your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt; from the constructor and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; method, so don’t just remove those!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But, you may ask, how do you get the decoder if it’s not in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Id&lt;/code&gt;? Good question. The answer: &lt;strong&gt;you need to register it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModInitializer&lt;/code&gt; on both ends (sender and receiver)&lt;/strong&gt;. In fact, Fabric API will happily crash if you don’t before calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerGlobalReceiver&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// SlapPacket is sent during gameplay&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// from the client to the server (serverbound; C2S)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;PayloadTypeRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;playC2S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Replace with configurationS2C, playS2C, etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, you can change the receiver. Instead of long parameters, the event callback now gets only 2 parameters: the payload that was sent, and a context object. (Don’t worry, it won’t eat the RAM.)&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- ServerPlayNetworking.registerGlobalReceiver(SlapPacket.TYPE, (packet, player, sender) -&amp;gt; {
-   var world = player.getServerWorld();
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ServerPlayNetworking.registerGlobalReceiver(SlapPacket.PACKET_ID, (payload, context) -&amp;gt; {
+   var world = context.player().getServerWorld();
&lt;/span&gt;    var entity = world.getEntity(packet.slapped());
&lt;span class=&quot;err&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here are the available fields in the context object:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadTypeRegistry&lt;/code&gt;&lt;/th&gt;
      &lt;th&gt;Class&lt;/th&gt;
      &lt;th&gt;Context Fields&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playC2S&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerPlayNetworking&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;player&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;responseSender&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playS2C&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientPlayNetworking&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;player&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;responseSender&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configurationC2S&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerConfigurationNetworking&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;networkHandler&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;responseSender&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configurationS2C&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientConfigurationNetworking&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;responseSender&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Note that the field shortcuts might be added later.&lt;/p&gt;

&lt;p&gt;Finally, sending the packet also uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomPayload&lt;/code&gt;. &lt;strong&gt;Remember to register the codec first&lt;/strong&gt;!&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;ClientPlayNetworking&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// for PacketSender:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sendPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SlapPacket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketSender&lt;/code&gt; no longer provides APIs that use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;.&lt;/strong&gt; For login networking where custom payloads are not used yet, use the subinterface &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoginPacketSender&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Some other Networking API related changes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FutureListeners&lt;/code&gt; was removed.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GenericFutureListener&lt;/code&gt;-taking methods in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketSender&lt;/code&gt; were removed. Use the one taking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCallbacks&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerPlayNetworking#getServer&lt;/code&gt; was removed. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handler.player.server&lt;/code&gt; should work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;networking-adjacent-changes-in-fabric-api&quot;&gt;Networking-adjacent changes in Fabric API&lt;/h3&gt;
&lt;h4 id=&quot;particles-api&quot;&gt;Particles API&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricParticleTypes#complex&lt;/code&gt; now requires you to pass both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codec&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt; for serializing the particle type. The string-based parser, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParticleType.Factory&lt;/code&gt;, was removed.&lt;/p&gt;

&lt;h4 id=&quot;recipe-api-1&quot;&gt;Recipe API&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomIngredientSerializer&lt;/code&gt; must now override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getPacketCodec&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; methods were removed. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ingredient#PACKET_CODEC&lt;/code&gt; for representing another ingredient (which Fabric API patches up to also support ours).&lt;/p&gt;

&lt;h4 id=&quot;screen-handler-api&quot;&gt;Screen Handler API&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExtendedScreenHandlerType&lt;/code&gt; now uses a payload object instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf&lt;/code&gt;. In the type constructor, you now need to pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketCodec&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExtendedScreenHandlerType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;OvenScreenHandler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;OVEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExtendedScreenHandlerType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syncId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inventory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;OvenData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PACKET_CODEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that the callback got &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buf&lt;/code&gt;, as well. Note that the payload object can be of any type, whether it be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt; or your custom record. (These don’t have to be registered in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PayloadTypeRegistry&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExtendedScreenHandlerFactory#writeScreenOpeningData&lt;/code&gt; was replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getScreenOpeningData&lt;/code&gt;. It takes the player as the sole argument and returns the data class, in this case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OvenData&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;registries&quot;&gt;Registries&lt;/h3&gt;
&lt;h4 id=&quot;registrywrapper--datagen&quot;&gt;RegistryWrapper &amp;amp; datagen&lt;/h4&gt;
&lt;p&gt;Many methods for serialization now require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryWrapper.WrapperLookup&lt;/code&gt; instance. This is used to query registries, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DynamicRegistryManager&lt;/code&gt; instance can be used for this purpose. This change is most prominent in text and data generation-related code. This registry is used to query data-driven values during serialization.&lt;/p&gt;

&lt;p&gt;Data provider constructors in Fabric API now take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryWrapper.WrapperLookup&lt;/code&gt; as a parameter; modders should change their constructors to take the instance and pass to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super&lt;/code&gt; constructor. In addition, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricAdvancementProvider#generateAdvancement&lt;/code&gt; now also passes the instance.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;public class TestBlockLootTableProvider extends FabricBlockLootTableProvider {
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;-    private TestBlockLootTableProvider(FabricDataOutput output) {
-        super(output);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+    private TestBlockLootTableProvider(FabricDataOutput output, CompletableFuture&amp;lt;RegistryWrapper.WrapperLookup&amp;gt; registryLookup) {
+        super(output, registryLookup);
&lt;/span&gt;    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;loot-registries&quot;&gt;Loot Registries&lt;/h4&gt;
&lt;p&gt;Loot tables (including loot-adjacent stuff, namely predicates and item modifiers) are now managed by a special type of registry, called “reloadable registries”. Unlike ordinary registries, they are reloaded during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/reload&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootDataLookup&lt;/code&gt; was removed; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReloadableRegistries.Lookup&lt;/code&gt; can be obtained from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server.getReloadableRegistries()&lt;/code&gt;. From there, item modifiers and predicates can be looked up via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRegistryManager&lt;/code&gt;; a shortcut exists for loot tables via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getLootTable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Registry-ification of loot table also means that they are now identified with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&lt;/code&gt;. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey.of(RegistryKeys.LOOT_TABLE, id)&lt;/code&gt; to get the registry key. In Fabric API, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VillagerInteractionRegistries#registerGiftLootTable&lt;/code&gt; now takes the registry key, while the ID-taking method is deprecated.&lt;/p&gt;

&lt;p&gt;Fabric API’s Loot API received breaking changes. For the arguments passed to events, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceMaanger&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootManager&lt;/code&gt; is gone. In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOAD_ALL&lt;/code&gt; event, the loot manager was replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Registry&amp;lt;LootTable&amp;gt;&lt;/code&gt;. In all places, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt; is replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&lt;/code&gt; as described above. In addition, because mutating registry is impossible now, the loot tables are modified before addition; this means that per-table events don’t get the table registry anymore.&lt;/p&gt;

&lt;h4 id=&quot;other-changes&quot;&gt;Other changes&lt;/h4&gt;
&lt;p&gt;A new syncing protocol is in place for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DynamicRegistryManager&lt;/code&gt; entries. Vanilla data packs provide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;knownPackInfo&lt;/code&gt; fields, which are sent by the server on joined clients. Clients then reply with the subset of the info they understand (i.e. loaded on their side). When a registry entry is loaded from a pack with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;knownPackInfo&lt;/code&gt;, and the client has acknowledged the info for the pack, the server tells the client to refer to its own copy of the data, skipping sending the serialized entry over the network. Most importantly, &lt;strong&gt;this is currently not used by mod-provided packs&lt;/strong&gt;, so the registry entries from mods will be sent even if the client has the same mod.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleRegistry&lt;/code&gt; no longer supports changing the registered value post-registration (such as by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; method). For this reason, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryEntryRemovedCallback&lt;/code&gt; event and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registeyEntryRemoved&lt;/code&gt; shortcut in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DynamicRegistryView&lt;/code&gt; were removed.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SculkSensorFrequencyRegistry.register&lt;/code&gt; now takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RegistryKey&amp;lt;GameEvent&amp;gt;&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameEvent&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;blocks&quot;&gt;Blocks&lt;/h3&gt;
&lt;p&gt;All &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AbstractBlock&lt;/code&gt; public methods to be overridden were made &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protected&lt;/code&gt; and no longer marked as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Deprecated&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity entity, BlockHitResult hit) {
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity entity, BlockHitResult hit) {
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;enchantments&quot;&gt;Enchantments&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enchantment&lt;/code&gt; constructor now takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enchantment.Properties&lt;/code&gt;, a record of enchantment properties. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnchantmentTarget&lt;/code&gt; enum was replaced with tags that specifies enchantment-supporting items.&lt;/p&gt;

&lt;h3 id=&quot;brewing&quot;&gt;Brewing&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBrewingRecipeRegistry&lt;/code&gt; was replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBrewingRecipeRegistryBuilder&lt;/code&gt;. The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FabricBrewingRecipeRegistryBuilder.BUILD&lt;/code&gt; event can be used to add new recipes to the brewing stand.&lt;/p&gt;

&lt;h3 id=&quot;entities&quot;&gt;Entities&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpawnRestriction.Location&lt;/code&gt; enum was replaced with an interface, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpawnLocation&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpawnLocationTypes&lt;/code&gt; provides predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpawnLocation&lt;/code&gt;s.&lt;/p&gt;

&lt;h3 id=&quot;client&quot;&gt;Client&lt;/h3&gt;
&lt;p&gt;In GUI, setting the initial focus of a screen is now done by overriding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setInitialFocus&lt;/code&gt;, rather than calling it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MatrixStack&lt;/code&gt; was replaced with the actual matrix in several rendering code.&lt;/p&gt;

&lt;h4 id=&quot;rendering&quot;&gt;Rendering&lt;/h4&gt;
&lt;p&gt;Some places that previously take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rgb&lt;/code&gt; was updated to take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argb&lt;/code&gt; instead. The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DyedColorComponent&lt;/code&gt; takes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argb&lt;/code&gt;. Item color providers also take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argb&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rgb&lt;/code&gt;, so make sure to wrap your color with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ColorHelper.Argb.fullAlpha()&lt;/code&gt; or else your item may appear transparent if it is registered to the translucent render layer. Block color providers also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argb&lt;/code&gt; now, but passing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rgb&lt;/code&gt; still works.&lt;/p&gt;

&lt;h3 id=&quot;other&quot;&gt;Other&lt;/h3&gt;
&lt;p&gt;DataFixerUpper was updated. This includes several breaking changes, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MapCodec&lt;/code&gt; being used in places defining extra fields. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RecordCodecBuilder#mapCodec&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create&lt;/code&gt; in this case. Another significant change: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;optionalFieldOf&lt;/code&gt; is now strict by default. This means that a decoding error in the field value is now treated as an error, instead of being silently skipped. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lenientOptionalFieldOf&lt;/code&gt; method restores old behavior.&lt;/p&gt;

&lt;p&gt;On the Minecraft game code side, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Util#getResult&lt;/code&gt; was replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decode(...).getOrThrow()&lt;/code&gt; method. Several methods and fields in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codecs&lt;/code&gt; were moved to the DFU itself, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;either&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xor&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;withAlternative&lt;/code&gt; (formerly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codecs#alternatively&lt;/code&gt;).&lt;/p&gt;</content><author><name></name></author><summary type="html">Minecraft 1.20.5 is to be released in the near future with significant changes affecting mod makers.</summary></entry><entry><title type="html">Fabric for Minecraft 1.20.3 &amp;amp; 1.20.4</title><link href="https://fabricmc.net/2023/11/30/1203.html" rel="alternate" type="text/html" title="Fabric for Minecraft 1.20.3 &amp;amp; 1.20.4" /><published>2023-11-30T00:00:00+00:00</published><updated>2023-11-30T00:00:00+00:00</updated><id>https://fabricmc.net/2023/11/30/1203</id><content type="html" xml:base="https://fabricmc.net/2023/11/30/1203.html">&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;fabric-changes&quot;&gt;Fabric changes&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;h3 id=&quot;loader-015&quot;&gt;Loader 0.15&lt;/h3&gt;
&lt;p&gt;Fabric Loader 0.15 has been released recently, which features built-in support for LlamaLad7’s &lt;a href=&quot;https://github.com/LlamaLad7/MixinExtras&quot;&gt;MixinExtras&lt;/a&gt; library. This version is currently in beta. Should you discover compatibility issues with mods that already bundle MixinExtras, please &lt;a href=&quot;https://github.com/FabricMC/fabric-loader/issues&quot;&gt;file a bug report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;MixinExtras is a companion library to Mixin, providing &lt;a href=&quot;https://github.com/LlamaLad7/MixinExtras/wiki&quot;&gt;new annotations&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;Please note that Fabric Loader 0.15 went through a number of internal changes, notably the transition from &lt;a href=&quot;https://github.com/FabricMC/tiny-mappings-parser&quot;&gt;TMP&lt;/a&gt; to &lt;a href=&quot;https://github.com/FabricMC/mapping-io&quot;&gt;Mapping-IO&lt;/a&gt; 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.&lt;/p&gt;

&lt;h3 id=&quot;loom-14&quot;&gt;Loom 1.4&lt;/h3&gt;
&lt;p&gt;Loom 1.4 includes enhancement for decompilers, support for deprecated modules in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabricApi.module&lt;/code&gt; (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.&lt;/p&gt;

&lt;p&gt;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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;genSourcesWithVineflower&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;genSources&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;div class=&quot;language-gradle highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fabricApi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configureDataGeneration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;new-fabric-api-changes&quot;&gt;New Fabric API changes&lt;/h3&gt;
&lt;p&gt;With the help of many contributors, Fabric API has received some new features since the last update blog post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Data Generation: add a method to register custom keys with priorities (ErrorCraft) &lt;!-- added after the blogpost, before 1.20.2 release --&gt;&lt;/li&gt;
  &lt;li&gt;Loot API: add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootTableEvents.LOADED&lt;/code&gt; (LLytho)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to those new features, this update also contains performance improvements for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketType&lt;/code&gt;-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!&lt;/p&gt;

&lt;h3 id=&quot;breaking-changes-in-1203&quot;&gt;Breaking changes in 1.20.3&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockSetTypeRegistry&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WoodTypeRegistry&lt;/code&gt; of the Object Builder API, previously deprecated, were removed. Please use the builders provided in the same API.&lt;/p&gt;

&lt;p&gt;The following APIs in the Transfer API module, all previously deprecated, were removed.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContainerItemContext#withInitial&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage#simulateInsert&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;simulateExtract&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exactView&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;minecraft-changes&quot;&gt;Minecraft changes&lt;/h2&gt;
&lt;p&gt;Minecraft 1.20.3 introduces some breaking changes to major developer-facing APIs.&lt;/p&gt;

&lt;h3 id=&quot;block-codecs&quot;&gt;Block codecs&lt;/h3&gt;
&lt;p&gt;Mojang now uses codecs to serialize blocks - specifically, instances of a particular type of block. You might need to implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getCodec&lt;/code&gt; method in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Block&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;However, the block codecs are &lt;strong&gt;currently unused&lt;/strong&gt;. This means that you can return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; or throw &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnsupportedOperationException&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getCodec&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3 id=&quot;text&quot;&gt;Text&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Text&lt;/code&gt; 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.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Important change: &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Text#translatable&lt;/code&gt; now expects all arguments to be numbers, boolean, strings, or other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Text&lt;/code&gt;s.&lt;/strong&gt; To pass things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockPos&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Identifier&lt;/code&gt;, which were previously implicitly converted to strings, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stringifiedTranslatable&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;For those who have previously used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Codecs.TEXT&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STRINGIFIED_TEXT&lt;/code&gt;, it’s time to switch to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextCodecs.CODEC&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextCodecs.STRINGIFIED_CODEC&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Text.Serializer&lt;/code&gt; inner class was split into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Serializer&lt;/code&gt; (to use as a Gson adapter) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Serialization&lt;/code&gt; (contains static methods). The methods were also renamed; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toJson&lt;/code&gt; is now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toJsonString&lt;/code&gt; to clarify return value.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Style.Serializer&lt;/code&gt; is gone; it is now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Style.Codecs&lt;/code&gt; and holds the codec only.&lt;/li&gt;
  &lt;li&gt;In related news, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PacketByteBuf#readUnlimitedText&lt;/code&gt; was added; this reads an infinite amount of text with no size limit. Most S2C packets now use this.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ticks&quot;&gt;Ticks&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tick&lt;/code&gt; 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:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getTickManager().shouldTick()&lt;/code&gt; to check if things should tick in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;START_WORLD_TICK&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;END_WORLD_TICK&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;START_SERVER_TICK&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;END_SERVER_TICK&lt;/code&gt; event.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TickManager&lt;/code&gt; can be obtained from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MinecraftServer#getTickManager&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;World#getTickManager&lt;/code&gt; (works with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientWorld&lt;/code&gt; as well).&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shouldSkipTick&lt;/code&gt; for checking if an entity should be ticked (beware, it is the inverse of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shouldTick&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Note: &lt;strong&gt;You do not need to call these checks inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Entity&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockEntity&lt;/code&gt; tick methods or events.&lt;/strong&gt; Only call inside server/world tick events.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is also now possible for the game to run faster or slower than 50 MSPT intentionally (as opposed to through lag). Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TickManager#getMillisPerTick()&lt;/code&gt; to determine the intended MSPT.&lt;/p&gt;

&lt;h3 id=&quot;blocks&quot;&gt;Blocks&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AbstractBlock#randomTick&lt;/code&gt; no longer calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scheduledTick&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlockSetType&lt;/code&gt; received new fields specifying pressure plate activation conditions and button interactions with projectiles/Breezes.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ColoredFallingBlock&lt;/code&gt; was added, replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GravelBlock&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SandBlock&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PowderSnowCauldronBlock&lt;/code&gt; was removed; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LeveledCauldronBlock&lt;/code&gt; handles the logic now.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransparentBlock&lt;/code&gt; was split into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TranslucentBlock&lt;/code&gt;, which renders in a translucent way (like slime and ice blocks), and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransparentBlock&lt;/code&gt;, which extends &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TranslucentBlock&lt;/code&gt; and is used by grates and glass blocks. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AbstractGlassBlock&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GlassBlock&lt;/code&gt; were removed.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FernBlock&lt;/code&gt; is renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ShortPlantBlock&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SaplingGenerator&lt;/code&gt; is now in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block&lt;/code&gt; package, and individual generator classes were removed and replaced with fields.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AbstractBlock#onStateReplaced&lt;/code&gt; implementations for block entities were consolidated to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemScatterer#onStateReplaced&lt;/code&gt;. Make sure to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super&lt;/code&gt; AFTER calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemScatterer&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootableContainerBlockEntity&lt;/code&gt; logics were split into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootableInventory&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkLootInteraction&lt;/code&gt; was renamed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generateLoot&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootableContainerBlockEntity&lt;/code&gt; still implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LootableInventory&lt;/code&gt;, but this allows other block entities like decorated pots to share the logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;entities&quot;&gt;Entities&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Boats, minecarts, and other player-constructed vehicles should now extend &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VehicleEntity&lt;/code&gt;. This provides the wobble effect seen when hitting that entity.&lt;/li&gt;
  &lt;li&gt;Various non-living entities (including projectiles and TNT) received &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyFrom&lt;/code&gt; override to copy the owner.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersistentProjectileEntity&lt;/code&gt; and its subclasses now take the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ItemStack&lt;/code&gt; in the constructor, representing the item stack form that players can pick up. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getItemStack&lt;/code&gt; returns the stack as-is, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asItemStack&lt;/code&gt; returns a copy (potentially reflecting the changes like potion override).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SpawnReason&lt;/code&gt; got two methods: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnySpawner&lt;/code&gt; (spawner &amp;amp; trial spawner) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isTrialSpawner&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canSpawn&lt;/code&gt; methods should check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnySpawner&lt;/code&gt;, and make the entity exempt from biome/height requirements imposed for natural spawn.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;client&quot;&gt;Client&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PopupScreen&lt;/code&gt; 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, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Builder&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CheckboxWidget&lt;/code&gt; is now built using a builder.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntryListWidget&lt;/code&gt; no longer takes the bottom coordinate in the constructor. It also actually became a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Widget&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClickableWidget#render&lt;/code&gt; was made &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;final&lt;/code&gt; to prevent overrides of that method from not calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super.render&lt;/code&gt; and preventing the tooltip from rendering. Subclasses must override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;renderWidget&lt;/code&gt; instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;misc&quot;&gt;Misc&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CommandManager#execute&lt;/code&gt; methods no longer return an integer return value. To get the return value, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServerCommandSource#withReturnValueConsumer&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RecipeProvider&lt;/code&gt; methods received some changes. Some JSON builders and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generateCookingRecipes&lt;/code&gt; now require passing the constructor of recipe class, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CampfireCookingRecipe::new&lt;/code&gt;. Other builders no longer require the serializer.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityType#HEROBRINE&lt;/code&gt; was removed. (Wait, was this ever added in the first place?)&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">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.</summary></entry></feed>