Fabric for Minecraft 1.20
Minecraft 1.20 - the Trails and Tales Update - releases on June 7th 2023, again with a number of changes that impact many mods.
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.2 (at the time of writing) to develop for Minecraft 1.20. Players should install the latest stable version of Fabric Loader (currently 0.14.19) to play 1.20.
Loom 1.2
Loom 1.2 is a small update focused on game library handling improvements and official Windows ARM native support. Loom 1.2 requires Gradle 8.1.
New Fabric API changes
Fabric API added many features since the last update blog post:
- Data Generation: add codec data provider. (ErrorCraft)
- Interaction Events: provide fake player API. (Technici4n)
- Networking: add packet-based API similar to vanilla networking system. See the gist for migration tips. Note that the existing API is not deprecated in any way. (apple502j)
- Renderer API: add material inspection and glint material property, remove texture indices. (PepperCode1, Technici4n)
- Transfer API: add slotted storage and non-empty iterator. (Technici4n)
- Other small additions to various APIs, such as Convention Tag and Object Builder
Breaking changes and deprecations
Aside from changes related to Minecraft code changes (which are discussed below), no breaking change to the API was introduced.
During one of the code refactors, one bug related to the Registry Sync was “accidentally” fixed. The bug previously allowed clients with Fabric API (but without content mods) to join a server with modded contents, despite the mod being missing on the client. The refactor was merged to both 1.19.4 and 1.20 snapshot branches; however, the bug was reintroduced to 1.19.4 only to prevent unexpected breakage. If you have previously relied on the bug, make sure to have users install the mods on the client.
A few rarely-used APIs within EventFactory
were deprecated. They were intended to be used for profiling events; however, the standard Java profiler provides a better result.
invalidate
method was terminally deprecated, to be removed in future versions.isProfilingEnabled
method was deprecated and now always returnsfalse
.getHandlerName
method was also deprecated.
Fabric Rendering API deprecations
Many methods of the renderer API had an int spriteIndex
parameter that was always 0. It was removed, and the naming of some methods was improved in the process. The boolean disableAo
material property was also replaced by a more flexible TriState for ambientOcclusion
.
The old methods are now deprecated, here are a few examples of migrating away from them:
MaterialFinder finder = ...;
- materialFinder.blendMode(0, <blend mode>);
+ materialFinder.blendMode(<blend mode>);
- materialFinder.disableAo(0, true);
+ materialFinder.ambientOcclusion(TriState.FALSE);
QuadView quadView = ...;
- quadView.spriteColor(0, -1, -1, -1, -1);
+ quadView.color(-1, -1, -1, -1);
The full list of renames can be found in the pull request description.
The new methods do not have a default implementation in 1.20. This does not affect mods using the Renderer API, however third-party renderers such as Canvas or Indium must add support for them.
Minecraft changes
Minecraft 1.20 introduces some breaking changes to major developer-facing APIs.
Material (or the lack thereof)
Material
was a class that indicated the type of blocks, such as plant or metal. This class no longer exists:
- To specify the properties, such as the map color and whether the block is replaceable, use the block settings.
One note on the new
solid
andnotSolid
block settings: These two methods override the default solid block check. If a block is not specified as solid or not solid explicitly, then the game checks whether the shape’s average side length is more than 0.73 OR whether the block is taller than 1 block. If either is true, the block is solid. - To get those values, use
BlockState
methods. (You may need to refactor your code if your method takesBlock
instead ofBlockState
.) - To check if a block is of a certain type, use block tags or
instanceof
.
Related changes:
BlockSetType
now hascanOpenByHand
field, used by doors and trapdoors.Block#canMobSpawnInside
now takes aBlockState
. Previously it took no arguments.BlockState#blocksMovement
, which returnstrue
for all solid blocks except cobwebs and bamboo shoots, was added.Block.Settings#of
method was renamed tocreate
. Fabric API’sFabricBlockSettings#of
was renamed as well, and the old method was deprecated.- Fabric API:
FabricMaterialBuilder
was removed.
- new Block(AbstractBlock.Settings.of(Material.PLANT, MapColor.GREEN))
+ new Block(AbstractBlock.Settings.create().mapColor(MapColor.GREEN).pistonBehavior(PistonBehavior.DESTROY))
World changes
One of the biggest, yet subtle changes in this version is that Entity#world
is now private. Use Entity#getWorld
or Entity#getServerWorld
:
- World world = player.world;
+ World world = player.getWorld();
RedstoneView
provides redstone-related methods that previously existed in World
.
Screen and rendering changes
DrawableHelper
, a utility that is frequently used by subclassing it, turned into an object passed to rendering methods: DrawContext
. This replaces the various MatrixStack matrices
parameters. You usually do not need to construct one yourself.
- public void render(MatrixStack matrices) {
- RenderSystem.setShaderTexture(0, TEXTURE);
- drawTexture(matrices, ...);
+ public void render(DrawContext context) {
+ context.drawTexture(TEXTURE, ...); // texture ID is now specified here
The following new methods were added to DrawContext
, replacing other methods in various places:
setShaderColor
(wrapsRenderSystem
one, which still exists)drawTextWithShadow
(replacesTextRenderer#drawWithShadow
)drawText
(wrapsTextRenderer#draw
)drawTextWrapped
drawItem
drawItemWithoutEntity
drawItemInSlot
drawItemTooltip
drawTooltip
(replacesScreen#renderTooltip
)drawHoverEvent
In addition, various rendering methods now take DrawContext
instead of MatrixStack
. If you still somehow need the matrix stack, you can use DrawContext#getMatrices
.
Fabric API changes related to this:
- Rendering API’s
HudRenderCallback
, Screen API’sScreenEvents.beforeRender
, andScreenEvents.afterRender
now takeDrawContext
instead ofMatrixStack
. Screens.getItemRenderer
is removed. This can be easily replaced withMinecraftClient#getItemRenderer
, although this is usually not necessary.
And one unrelated change: Screen#passEvents
was removed, therefore screens can no longer pass events.
Item group changes
ItemGroup
s are now registered in a registry. This means that the vanilla game tracks them using identifiers, just like blocks and items - and it is registered in the same way as those.
- public static final ItemGroup ITEM_GROUP = FabricItemGroup.builder(new Identifier(MOD_ID, "example"))
- .icon(() -> new ItemStack(Items.DIAMOND_PICKAXE))
- .displayName(Text.translatable("example-mod.group.example"))
- .build();
+ public static final RegistryKey<ItemGroup> ITEM_GROUP = RegistryKey.of(RegistryKeys.ITEM_GROUP, new Identifier(MOD_ID, "example"));
+
+ @Override
+ public void onInitialize() {
+ Registry.register(Registries.ITEM_GROUP, ITEM_GROUP, FabricItemGroup.builder()
+ .icon(() -> new ItemStack(Items.DIAMOND_PICKAXE))
+ .displayName(Text.translatable("example-mod.group.example"))
+ .build()); // build() no longer registers by itself
+ }
Notice that FabricItemGroup#builder
takes no arguments now, since the ID is assigned by the registry. Note, you must now call displayName
manually or it will crash!
ItemGroupEvents.modifyEntriesEvent
will now take RegistryKey<ItemGroup>
instead of ItemGroup
or Identifier
. Note that vanilla ItemGroups
fields are now registry keys, so code using those just needs to be recompiled. And with the game now providing the identifier, IdentifiableItemGroup
is removed.
Finally, one small breaking change to Data Generation: FabricLanguageProvider.TranslationBuilder#add
will now take RegistryKey<ItemGroup>
instead of ItemGroup
.
ItemStack changes
Code modifying ItemStack
should now use the combined methods (such as copyWithCount
) instead of 2 method calls (such as copy
+ setCount
) to properly handle empty stacks. ItemStack#copyAndEmpty
was added to move the contents of one stack into a new copy.
- ItemStack copy = stack.copy();
- copy.setCount(1);
+ ItemStack copy = stack.copyWithCount(1);
A couple of equality methods in ItemStack
were removed:
ItemStack#isItemEqual
: use the staticareItemsEqual()
method instead.ItemStack#areNbtEqual
: usecanCombine
(which also checks for items) or compare NBT yourself instead.
Loot changes
Predicates and item modifiers (or, in legacy terms, loot conditions and loot functions) are now managed by LootManager
. They are identified using LootDataKey
, similar to RegistryKey
. getTable
is renamed to getLootTable
, and getElement
can be used to get loot tables, predicates, or item modifiers.
LootContext.Builder
is moved to LootContextParameterSet.Builder
and its parameter
method was renamed to add
. The putDrop
method was renamed to addDynamicDrop
. The getNullable
method was renamed to getOptional
for consistency. The loot inventory seed is now given via supplyInventory
.
Other small, but noteworthy changes
- Fabric Content Registries’
VillagerPlantableRegistry
was replaced withItemTags.VILLAGER_PLANTABLE_SEEDS
(data pack tags). - Herobrine was removed.
RecipeProvider#offerWoolDyeingRecipe
and similar methods were merged toofferDyeableRecipes
(which also offers re-coloring).ServerCommandSource#sendFeedback
now takesSupplier<Text>
instead ofText
for performance reasons. Add() ->
and it should be good to go.