Fabric for Minecraft 1.19
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 withLootTableEvents.REPLACE
event (for replacing an entire loot table) andLootTableEvents.MODIFY
event (for modifying part of a loot table).REPLACE
runs beforeMODIFY
, 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.