Minecraft 1.21.4, the Garden Awakens drop, releases December 3rd. Like with other updates, this drop contains some significant changes affecting 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.

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.

Fabric changes

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).

Deprecations and removals

The following deprecated module was removed: fabric-rendering-v0. FabricModelPredicateProviderRegistry, which was previously deprecated, was also removed.

BuiltinItemRenderer and BuiltinItemRendererRegistry from the Rendering v1 module were removed and have been replaced by a transitive access widener to SpecialModelTypes.ID_MAPPER.

AttachmentRegistry#builder was deprecated in favor of create methods. The old method is inconvenient, as it requires explicit type parameters. (See the “Data Attachment Syncing” section for an example.)

BlockPickInteractionAware was removed, the new pick item events should be used instead.

Breaking change

CustomIngredient#getMatchingStacks must now return a stream, not a list.

New Fabric API changes

With the help of many contributors, Fabric API has received some new features since the last update blog post:

  • Convention Tags: Add more tags (JT122406, TelepathicGrunt, IThundxr)
  • Data Attachments: Registration enhancements (forgetmenot13579)
  • Data Attachments: Sync API (Syst3ms)
  • Lifecycle Events: Add ServerChunkEvents.Generate (jpenilla)
  • Lifecycle Events: Add AFTER_CLIENT_WORLD_CHANGE (fishshi)
  • Transfer API: Add support for Item-containing Items (BasiqueEvangelist)

In addition, a longstanding bug that caused language files to not load after overriding assets/minecraft/lang/en_us.json in a dedicated server mod was fixed.

Data Attachment Syncing

Fabric API can now sync data attachments. To make a syncable attachment, call syncWith inside the builder. The passed packet codec is used to serialize the attached data. Here is how a thirst attachment would look like:

public static final AttachmentType<Integer> THIRST = AttachmentRegistry.create(
    Identifier.of("modid", "thirst"),
    builder -> builder 
        .initializer(() -> 20) // start with a default value like hunger
        .persistent(Codec.INT) // persist across restarts
        .syncWith(PacketCodecs.VAR_INT, AttachmentSyncPredicate.targetOnly()) // only the player's own client needs the value for rendering
    );

The sync predicate (AttachmentSyncPredicate) controls who gets the synced data. For example, global data can be synced using all(). For more granular control, you can also pass a custom predicate.

Pick item events

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 ClientPickBlockApplyCallback, ClientPickBlockCallback, and ClientPickBlockGatherCallback. This change also applies to entities (EntityPickInteractionAware).

The new events are PlayerPickItemEvents#BLOCK for picking a block and PlayerPickItemEvents#ENTITY for picking an entity(‘s spawn egg). Return ItemStack.EMPTY to stop the picking, and return null to use the default behavior.

PlayerPickItemEvents.BLOCK.register((player, pos, state, requestIncludeData) -> {
    if (state.isIn(MyTags.NOT_PICKABLE)) return ItemStack.EMPTY;

    return null; // use default behavior
})

requestIncludeData is true if the client requests NBT to be included in the returned item stack (by holding Ctrl 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).

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.

Client Data Generation

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 fabricApi utility to set up data generation:

  fabricApi {
-     configureDataGeneration()
+     configureDataGeneration {
+       client = true
+     }
  }

If you are using the createSourceSet option, your datagen source set will now have access to Minecraft’s client-only classes and classes in your client source set. Other than updating the data generators themselves, no other changes will be necessary.

If you are using the splitEnvironmentSourceSets option but not the createSourceSet option, you should move your DataGeneratorEntrypoint implementation from the main source set to the client source set.

Model Loading API

ModelModifier 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 UnbakedModel and are baked with settings while block models use GroupableModel (which no longer extends UnbakedModel) and are not baked with settings. It also allowed cleaning up the identifier getters and providing the BlockState directly to ModelModifier.OnLoadBlock.

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

ModelModifier.OnLoad can now accept a null model, which is a model that was requested during resolution but does not have a corresponding JSON file. With this change, ModelResolver was removed as its behavior could now be achieved with ModelModifier.OnLoad with OVERRIDE_PHASE.

DelegatingUnbakedModel was removed as GroupableModel no longer extends UnbakedModel, so BlockModelResolvers can no longer use it, which was its original purpose.

textureGetter was removed from ModelModifier callback contexts as it is now accessible through Baker#getSpriteGetter.

FRAPI’s WrapperBakedModel was moved to Model Loading API and was renamed to UnwrappableBakedModel to avoid conflicts with vanilla’s new WrapperBakedModel. UnwrappableBakedModel is also implemented and interface injected on vanilla’s WrapperBakedModel. A new static UnwrappableBakedModel#unwrap method was added which accepts a Predicate saying when to stop unwrapping. See the documentation for more details.

Minecraft changes

Block Models

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:

- @Override
- protected BlockRenderType getRenderType(BlockState state) {
-     return BlockRenderType.ENTITYBLOCK_ANIMATED;
- }

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

Item Models

Similar to the blockstate definition json files found in assets/<namespace>/blockstates, items now utilize new item model definition json files in assets/<namespace>/items to determine which models to use.

These can be quite simple…

{
  "model": {
    "type": "minecraft:model",
    "model": "modid:item/my_item"
  }
}

or more complex…

{
  "model": {
    "type": "minecraft:condition",
    "property": "minecraft:fishing_rod/cast",
    "on_false": {
      "type": "minecraft:model",
      "model": "modid:item/netherite_fishing_rod"
    },
    "on_true": {
      "type": "minecraft:model",
      "model": "modid:item/netherite_fishing_rod_cast"
    }
  }
}

utilising conditions and other logic to determine which model to use.

They also control applying color tints to item textures.

{
  "model": {
    "type": "minecraft:model",
    "model": "minecraft:item/template_spawn_egg",
    "tints": [
      {
        "type": "minecraft:constant",
        "value": 6925483
      },
      {
        "type": "minecraft:constant",
        "value": 12238402
      }
    ]
  }
}

These tints can be constant or based on other factors such as potion contents, map colors, etc.

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,

- {
-  "parent": "modid:block/maple_planks"
- }

at assets/modid/models/item/maple_planks.json can be removed, in favor of

+ {
+  "model": {
+    "type": "minecraft:model",
+    "model": "modid:block/maple_planks"
+  }
+ }

in assets/modid/items/maple_planks.json.

Additionally, ItemColors and related APIs for tinting items have been removed, as item color tints are now controlled by these files.

For further information, these jsons are well documented on the vanilla Minecraft wiki here and all the ones used by vanilla items can be easily found in the game files.

For modders using data generation, these can be generated much like any other JSON asset.

Miscellaneous

  • Resource Metadata files now use Codec serializers
  • Equipment assets were moved from assets/<namespace>/models/equipment to assets/<namespace>/equipment
  • The minecraft:tall_flowers block tag was removed
  • The minecraft:flowers, minecraft:tall_flowers, and minecraft:trim_templates item tags were removed
  • The minecraft:herobrine entity was removed
  • Trim Material jsons no longer specify an item model index, as trimmed items now use separate item models for each material
  • Textures for item outlines shown in empty slots in certain GUIs are now located in assets/<namespace>/textures/gui/sprites/container/slot

Yarn changes

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.

Some notable examples include:

  • The net/minecraft/data/client package got moved to net/minecraft/client/data, to reflect the classes now being client-only
  • To match this, the net/minecraft/data/server package was removed and its contents moved down to net/minecraft/data
  • All references to xp got changed to experience
  • BlockStateModelGenerator.TintType was changed to BlockStateModelGenerator.CrossType
  • CherryLeavesBlock was changed to ParticleLeavesBlock
  • CherryLeavesParticle was changed to LeavesParticle
  • LichenGrower was changed to MultifaceGrower
  • EntityModelLoader was changed to LoadedEntityModels
  • CocoaBeansTreeDecorator was changed to CocoaTreeDecorator
  • BakedQuad#colorIndex was changed to tintIndex