Minecraft 1.19: The Wild Update is now released, and along with it, updates for Fabric itself and many mods already.

For Players

Players should use Fabric Installer 0.11.0 and Fabric Loader 0.14.6 (at the time of writing) to play on Minecraft 1.19.

Plenty of mods have already updated to 1.19 already, and we expect many more to be on the way. Please be patient as mod developers dedicate some of their free time to updating their mods to this new version.

Fabric Changes For Mod Developers

Developers should use Loom 0.12 (at the time of writing) to develop for Minecraft 1.19.

Minecraft 1.19 introduces several code changes to major developer-facing APIs. In addition, Fabric has introduced several new ways for mod developers to safely develop server-side mods without accidentally relying on client-exclusive code.

New Fabric API features

Fabric API added many features since the last update blog post:

  • Data Generation: easily generate JSON files for blocks, recipes, advancements, etc… (modmuss50)
  • Entity API Lookup: flexible retrieval of object instances from entities. (deirn)
  • Resource Conditions: only enable select recipes, advancements, etc… when specific conditions are met. (Technici4n)
  • Transitive Access Widener module: directly use many private/protected classes and methods in vanilla. (Juuxel)
  • FluidVariant Attributes: define and access name, temperature, etc… of fluids. (Technici4n)
  • Convention Tags: define standard tags that Fabric mods can use, and register vanilla entries to them. (dexman545)
  • Loot API v2: replacement for the Loot Table API v1, with many improvements. The new version uses interface injection and transitive access wideners to implement most of its functionalities. Additionally, LootTableLoadingCallback was replaced with LootTableEvents.REPLACE event (for replacing an entire loot table) and LootTableEvents.MODIFY event (for modifying part of a loot table). REPLACE runs before MODIFY, and if one mod replaces a loot table, the callback loop will exit early and no other mod can replace the loot table. (Juuxel)
  • Message API (experimental): server-side manipulation of messages sent to players. (apple502j)
  • And many smaller features and bug fixes.

Deprecated Fabric API Modules

Fabric API modules that are deprecated (including the aforementioned Loot Table API v1, and the Command API v1) are no longer present in the default Maven artifact. Mods that wish to build against those modules must now depend on net.fabricmc.fabric-api:fabric-api-deprecated in build.gradle file for them to build successfully:

modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"

This should not impact players in any way, as the jar that is downloaded from CurseForge and Modrinth still contains all the modules.

Class Loader Isolation and Mixins

Fabric Loader 0.14 improves class loader isolation. This allows Mixins to apply to libraries that the game uses, such as Brigadier, DataFixerUpper, or Authlib. Mods using workarounds to allow mixins to apply to such libraries should remove the workaround.

Split Client And Common Code

In Loom 0.12 and Loader 0.14, an experimental option has been added to require all client code to be moved into its own sourceset: resources and common code will be in src/main, while client-only code will be in src/client. This provides a compile-time guarantee against calling client-only Minecraft code on the server. When building, Loom still produces a single jar that works on both the client and the server.

To enable split source sets, add the following to your mod’s build.gradle:

loom {
   splitEnvironmentSourceSets()

    mods {
        modid {
            sourceSet sourceSets.main
            sourceSet sourceSets.client
        }
    }
 }

As your mod will now be split across two sourcesets, you will need to use the new DSL to define your mod’s sourcesets. This enables Fabric Loader to group your mod’s classpath together.

Minecraft Changes For Mod Developers

Text Changes

Text should now be created using static methods provided by the Text interface rather than by using constructors. For example:

- new LiteralText(content);
- new TranslatableText(key, args);
+ Text.of(content);
+ Text.translatable(key, args);

In Yarn, the old classes are now called text contents (such as TranslatableTextContent) because they have been separated from the text structure (style and siblings). Mod developers will rarely need to interact with these text content classes.

Command Changes

Command arguments have been refactored to look up registry entries using the CommandRegistryAccess class, a wrapper around the registry manager. The registry access is an optimization for handling missing tag references, but must be passed into arguments during command registration:

- CommandManager.argument("item", ItemStackArgumentType.itemStack())
+ CommandManager.argument("item", ItemStackArgumentType.itemStack(registryAccess))

If you use Fabric API to register commands, you should switch to the version 2 of the Fabric Command API, which contains a major breaking change to provide the registry access. Unlike most of other breaking changes, this is an entirely new API with a new package.

- import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
+ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;

- CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
-    if (dedicated) {
+ CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
+    if (environment.dedicated) {
         dispatcher.register(...);
     }
  });

While version 1 of the API still exists for server-side registration, client commands functionality is no longer present in that version. If you use client commands, you must use version 2, which now uses an event for registration as well:

- import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager;
+ import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;

- ClientCommandManager.DISPATCHER.register(...);
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
+     dispatcher.register(...);
+ });

Secure Chat

Mojang has introduced a feature to cryptographically sign chat messages to detect whether the server modified the sent messages. Players sign all chat messages using a Mojang-provided private key, which the server and the clients verify. If the server modifies the message unexpectedly, the message cannot be verified, and clients can opt in to hide those messages.

Along with this, there were several protocol changes:

  • The client now wraps the message with chat.type.text message (or the like) instead of the server. To customize this, a custom message type (called “chat type” by the game) can be registered. (See below for details.)
  • Commands are sent in a separate packet, not as a slash-prefixed chat message.

This mostly impacts mods that change the chat message server-side in some ways like translating or coloring. To prevent the messages from being marked as “unverified”, the mod has to use one of the two options:

  • Client-side message decoration. A server can register a custom MessageType using a data pack (just like custom world generation), which consists of various “decorations” applied to the whole message. Chat Type Generator is a third-party tool that can generate the JSON file defining custom message types easily. Then, when sending a message, the mod should pass the registry key of the message type to be used.
RegistryKey<MessageType> typeKey = RegistryKey.of(Registry.MESSAGE_TYPE_KEY, new Identifier("modid", "orange"));
// when sending
server.getPlayerManager().broadcast(Text.of("This is in orange!"), typeKey);
  • Server-side message decorator. This can be used to modify the message content itself, as well as the styling applied. Fabric API provides a way to register a custom message decorator.
ServerMessageDecoratorEvent.EVENT.register(
    // Used to provide better compatibility across mods
    ServerMessageDecoratorEvent.CONTENT_PHASE,
    (sender, message) -> {
        if (message.getString().contains("tater")) {
            message = message.copy().append(" :tiny_potato:");
        }

        return CompletableFuture.completedFuture(message);
    }
)

Note that to sign the message produced by the message decorator, the server must enable “chat preview” by setting previews-chat=true in server.properties. When clients join such servers, they will receive a warning that the typed message will be sent to show the preview before sending. Clients can disable the chat previews via the options, which causes the decorated part of the message to be marked as “unsigned” (but not the original message).

Finally, it is recommended to check the Yarn javadoc, which provides documentation on how chat messages are handled.

Random Changes

The JDK java.util.Random class has been replaced entirely with Mojang’s own interface, net.minecraft.util.math.random.Random. Several implementations are available to provide different levels of thread safety. For most use cases, Random.create() should be used to create the random instance. Note that this random instance is not safe for multithreaded use.

Option Changes

Client options were completely refactored. There is a class, named SimpleOption, that handles everything an option needs - rendering, validation, serialization, etc. An instance holds its name, current value, default value, and a set of callbacks to provide customizable behaviors. For example, a slider-based integer option would use ValidatingIntSliderCallbacks, while a button-based option would use PotentialValuesBasedCallbacks. To get the value, use getValue(), and to set the value while validating, use setValue().

GameOptions class holds all options used by the vanilla game.

GameOptions options = MinecraftClient.getInstance().options;
GraphicsMode graphicsMode = options.getGraphicsMode().getValue();
options.getFov().setValue(80);
// setValue triggers validation, so this cannot set gamma more than the limit (1.0)
options.getGamma().setValue(5.0);

Tag Changes

The Tag class has been removed, after having been made largely obsolete in 1.18.2 due to the addition of TagKey.

The inner classes, which are still in use, have been moved to TagBuilder and TagEntry. The remaining usages in functions now use Collection. TagFile has been added, which is used to refer to a specific tag JSON file.

Additionally, many vanilla tags have been added or modified in 1.19. Ensure your modded content is in all the applicable tags. For example, villager workstations should now be added to the minecraft:acquirable_job_site tag.

Structure Changes

The game no longer refers to generated structures as “configured structure features”. Yarn mapping has renamed and several structure-related classes to handle this change; for example, StructureFeature has been renamed to Structure.

To avoid conflicts and to match the terminology used by custom world generation, the old Structure class was renamed to StructureTemplate, and StructureManager is now called StructureTemplateManager.

Seeded Sounds

The playSound methods now have a seed parameter. This seed is used to determine which sound is played for a sound event; as a result of this change, two players hearing the same sound event will now hear the same sound. Most mods will not need to change their code to support seeded sounds, as the playSound methods are overloaded to provide a default random seed.