Fabric for Minecraft 1.19.4
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
Ingredient
s. (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 inFluidStorage
andItemStorage
, which indicate full inventory without side restriction. exactView
method withtransaction
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 DamageSource
s. 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. BlockSetType
s 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. WoodType
s 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 callSaddledComponent#tickBoost
here.travelControlled
, fromItemSteerable#travel
.getControlledMovementSpeed
, which calculates the velocity from the user input.getSaddledSpeed
, which calculates the velocity of the entity. Multiply the value withSaddledComponent#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 inNbtHelper
are moved toDataFixTypes
.- There is now a method to update
Dynamic
s that aren’t NBT. getDataVersion
andputDataVersion
methods were added toNbtHelper
.DataResult#error
now expects aSupplier<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). UsegetMainWorkerExecutor
instead.