Minecraft 1.19.4 is almost here, with a number of changes that impact most mods. As noted previously, ‘minor’ releases starting from 1.19.3 can include major changes, and neither mod authors nor players should assume compatibility.

As usual, we ask players to be patient, and give mod developers time to update to this new version.

Here is a list of all major modder-facing changes in this version. Note that all code references are using Yarn mappings; modders using alternative mappings may need to use different names.

Fabric changes

Developers should use Loom 1.1 (at the time of writing) to develop for Minecraft 1.19.4. Players should install the latest stable version of Fabric Loader (currently 0.14.14) to play 1.19.4.

New Fabric API features

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

  • Language files provided by mods are now loaded on the server. (Teddy Li)
  • Recipe API: add custom Ingredients. (Technici4n)
  • Data Generation: support resource conditions in BlockLootTableGenerator.
  • GameTest: improve structure loading to support both NBT and SNBT-based structures. (apple502j)
  • Resource Conditions: add registry_contains condition. (Technici4n)
  • Added Client Message Events (Kevin, Juuz, Sideroo)
  • Other small additions to various APIs, such as Object Builder and Renderer API

Breaking changes and deprecations

In addition to changes described below, Transfer API received two breaking changes (applicable to 1.19.4):

  • Mods now need to handle null directions in FluidStorage and ItemStorage, which indicate full inventory without side restriction.
  • exactView method with transaction parameter, deprecated for removal, is removed. Use the transactionless method instead.

In Registry Sync, FabricRegistryBuilder no longer requires the type class to be passed - just the registry key. The old methods were deprecated.

In Block Render Layer API, BlockRenderLayerMap’s useless item-related methods were deprecated for removal.

Minecraft changes

Minecraft 1.19.4 introduces some breaking changes to major developer-facing APIs.

Item groups

ItemGroup registration changed again. Callback passed to ItemGroup.Builder#entries now takes two arguments, instead of three. Enabled features and operator permission flag are now passed via the context object.

private static final ItemGroup ITEM_GROUP = FabricItemGroup.builder(new Identifier(MOD_ID, "test_group"))
    .icon(() -> new ItemStack(Items.DIAMOND))
-   .entries((enabledFeatures, entries, operatorEnabled) -> {
+   .entries((context, entries) -> {
       entries.add(TEST_ITEM);
    })
    .build();

Damage types

With the addition of /damage, damage related code has been refactored.

Damage types can now be defined using a dynamic registry, with data packs. This also removed the constant DamageSources. The DamageSources class holds several methods to get instances of DamageSource with or without an attacker:

- targetEntity.damage(DamageSource.MAGIC, 4.0F);
- anotherEntity.damage(DamageSource.anvil(attacker), 1.0F);
+ targetEntity.damage(world.getDamageSources().magic(), 4.0F);
+ anotherEntity.damage(world.getDamageSources().fallingAnvil(attacker), 1.0F);

getDamageSources method also exists in Entity as a shortcut.

To check if damage is of a certain type, tags should be used. Several data pack predicates related to damages have changed to reflect this.

Many damage related checks previously hardcoded in the game, such as fall damage-immune mobs (via handleFallDamage override), are now handled using entity and damage type tags.

Block set types

Sounds of various blocks, such as doors, trapdoors, buttons, pressure plates, etc. are now configured by passing an instance of a new class, BlockSetType, to the respective block constructors. BlockSetTypes can be created and registered using Object Builder API’s BlockSetTypeRegistry.

Similarly, signs and fence gates use the class WoodType to determine their sounds and sign textures. WoodTypes require a BlockSetType, and can be registered using WoodTypeRegistry.

Biome

Biome precipitation is now a boolean. Whether it rains or snows is now entirely dependent on temperature and is positional; if the temperature is below 0.15, it snows. Biome Modification API’s setPrecipitation method now takes a boolean to reflect this, and Biome#getPrecipitation and hasPrecipitation methods were added to reflect this. Biome#isHot is removed and replaced with tags for specific usecases.

Biome JSON files should now have a boolean has_precipitation field, not enum precipitation field.

GUIs and rendering

RenderSystem#enableTexture and disableTexture has been removed. They are no longer necessary.

Most rendering methods now take MatrixStack if they did not already. With this, DrawableHelper#getZOffset is now gone, and all DrawableHelper methods have turned into static methods, along with some Yarn renames:

  • drawCenteredText -> drawCenteredTextWithShadow
  • drawStringWithShadow/drawWithShadow -> drawTextWithShadow

ModelTransformation.Mode is replaced with ModelTransformationMode (notice the lack of dot). TextRenderer methods now take TextLayerType, instead of boolean seeThrough.

GUI code has received changes to support new keyboard navigation. After each keyboard navigation, the game recalculates the focused element; it creates a tree of elements, making sure only one element is focused at a time. Screen implementations should call setInitialFocus within the init method.

ScreenHandlerType now requires a required feature set to be passed. This is usually FeatureFlags.VANILLA_FEATURES.

Recipes

Many recipe related methods now require a DynamicRegistryManager instance to be passed.

Entities

Entity#stepHeight is now private. This must now be set using setStepHeight. The getter getStepHeight is added as well.

References to “scoreboard tag” (/tag) are now renamed to “command tag”.

getCausingEntity/setCausingEntity and other owner-related methods have been merged into getOwner and setOwner.

Several changes have been made to vehicles. ItemSteerable methods are moved to LivingEntity, and SaddledComponent fields are now private. The following methods were added to LivingEntity:

  • tickControlled, which is called every tick if the entity is being ridden and controlled by other entity. Set the entity rotation and call SaddledComponent#tickBoost here.
  • travelControlled, from ItemSteerable#travel.
  • getControlledMovementSpeed, which calculates the velocity from the user input.
  • getSaddledSpeed, which calculates the velocity of the entity. Multiply the value with SaddledComponent#getSpeed and return here.

Additionally, LivingEntity#getOffGroundSpeed was added. This controls the entity velocity when it is falling or flying.

Equipment

Wearable is renamed to Equipment, and is now implemented by shields. Equipment items must now also implement getSlotType method.

ArmorItem constructor now takes an ArmorItem.ArmorType instead of an EquipmentSlot.

BlockPos changes

Vec3i and BlockPos constructors that take double or Position (such as Vec3d) are moved to ofFloored method. This makes it clear which rounding mode is used.

- BlockPos pos = new BlockPos(3.14, 0.0, 3.14);
- BlockPos pos2 = new BlockPos(entity.getPos());
+ BlockPos pos = BlockPos.ofFloored(3.14, 0.0, 3.14);
+ BlockPos pos2 = BlockPos.ofFloored(entity.getPos());

Texts

TranslatableTextContent now supports text fallbacks, used when no matching translation is found. To construct texts with fallbacks, use Text#translatableWithFallback.

ScreenTexts received CONTINUE and SPACE predefined texts, as well as a space method for chaining; for example space().append(text).

Data fixers

The library that powers serialization codecs and world file updates, DataFixerUpper, received major performance improvements both in startup and update time.

The library update and corresponding Minecraft changes are as follows:

  • update methods in NbtHelper are moved to DataFixTypes.
  • There is now a method to update Dynamics that aren’t NBT.
  • getDataVersion and putDataVersion methods were added to NbtHelper.
  • DataResult#error now expects a Supplier<String>, to lazy-evaluate the error message.
  • Util#getBootstrapExecutor is removed, because its only use was off-thread DataFixerUpper optimization (which is no longer off-thread). Use getMainWorkerExecutor instead.