-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
340 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,340 @@ | ||
--- | ||
layout: post | ||
title: Fabric for Minecraft 1.21.2 | ||
ref: 1212 | ||
--- | ||
Minecraft 1.21.2, the "Bundles of Bravery" drop, is expected to release soon. Mojang has recently [announced](https://www.minecraft.net/en-us/article/the-future-of-minecrafts-development) that they will release these "drops" throughout the year. 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 ask everyone kindly not to pester them. **We also recommend all players to make a backup of their worlds.** | ||
|
||
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.8 (at the time of writing) to develop mods for Minecraft 1.21.2. Players should install the latest stable version of Fabric Loader (currently 0.16.7). | ||
|
||
### Fabric Loader changes | ||
|
||
Fabric Loader 0.16.0 was released some time ago. Most notably, this release updates the bundled MixinExtras to 0.4.0. | ||
|
||
In addition, Fabric Loader 0.16.7 added support for Java 23. However, you should continue to use Java 21 for mod development and gameplay. | ||
|
||
#### MixinExtras additions | ||
|
||
The following new features have been added: | ||
|
||
- [`@WrapMethod`](https://github.com/LlamaLad7/MixinExtras/wiki/WrapMethod), which allows wrapping the entire method | ||
- [`@Cancellable`](https://github.com/LlamaLad7/MixinExtras/wiki/Cancellable), which allows cancellation from all injectors. | ||
- `namespace` parameter in [`@Share`](https://github.com/LlamaLad7/MixinExtras/wiki/Share) to share values between Mixins | ||
|
||
### Loom 1.8 | ||
|
||
Loom 1.8 adds support for configuration caches, Gradle 8.10, and other changes and fixes. | ||
|
||
Configuration cache is an opt-in Gradle performance enhancement feature that will be enabled by default in Gradle 9. Because this may break existing setup, we only recommend using this if you are familiar with Gradle buildscripts. To support this change, multi-project optimization has been removed. | ||
|
||
### 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 (TelepathicGrunt, Juuz) | ||
- Crash Report Info: Print the full stack trace from the dedicated server watchdog (TelepathicGrunt) | ||
- Entity Events: Add after damage event (TheDeathlyCow) | ||
- Item API: Modify enchantment and add component map builder extensions (TheDeathlyCow) | ||
- Item Group API: Add API to control creative inventory screen (modmuss50) | ||
- Loot API: Loot API v3 (modmuss50) | ||
- Networking: Add MinecraftClient/Server instances to networking contexts (modmuss50) | ||
- Networking: Add `ClientConfigurationConnectionEvents#START` (modmuss50) | ||
- Networking: Add access to ClientConfigurationNetworkHandler in context (Earthcomputer) | ||
- Object Builder: Add an API to add additional supported blocks to block entity types (modmuss50) | ||
- Renderer API: Add `ShadeMode` (PepperCode1) | ||
- Renderer API: Quads overloads for joml interfaces (SHsuperCM) | ||
- Resource Conditions: Allow conditions inside pack overlays (Apollo) | ||
- Resource Loader: Add API to create reload listeners with a registry lookup (modmuss50) | ||
- Removed Herobrine (Tiny Potato) | ||
- Transfer API: Crafter support (modmuss50) | ||
- Transfer API: Add `ItemVariant#withComponentChanges` (BasiqueEvangelist) | ||
|
||
### Breaking changes and deprecations | ||
|
||
*Note: breaking changes related to vanilla changes are addressed separately below.* | ||
|
||
One deprecated module was removed: `fabric-renderer-registries-v1`. | ||
|
||
In Resource Condition, the `test` method now takes `RegistryOps.RegistryInfoGetter`. Tags can no longer have resource conditions. Similarly, in Resource Loader, `ResourceReloadListenerKeys#TAGS` was removed. | ||
|
||
The following deprecations were made since the last blogpost: | ||
|
||
- Content Registries: `VillagerInteractionRegistries#registerCollectable` was deprecated. Use the vanilla tag, `minecraft:villager_picks_up`, instead. | ||
- Loot API: Loot API v2 was deprecated. Use Loot API v3, which passes registry contexts, instead. | ||
- Networking:`ClientConfigurationConnectionEvents#READY` was renamed to `COMPLETE`. (This was done during the 1.21 update cycle, but after we published the last blogpost.) | ||
|
||
## Minecraft changes | ||
|
||
### `ServerWorld` parameters | ||
|
||
Many methods that must be executed on the server side only now require `ServerWorld` to be passed explicitly. **Do not cast just to fix a type error;** many events and overridden method are still called on both the client side and the server side. | ||
|
||
Instead, wrap all logic that must be run only on the server side with `if (world instanceof ServerWorld serverWorld)`. The `serverWorld` can be passed to those methods. | ||
|
||
For example, `Entity#damage` now requires `ServerWorld`, and is therefore only called on the server side. There is an additional method, `clientDamage`, which is called only on the client side. | ||
|
||
### Block and item settings | ||
|
||
Minecraft 1.21.2 uses registry keys to pre-compute certain block or item settings. This allows referencing them in default item components. For example, rather than computing a default name based on an item's registry key inside `getName` method if the `minecraft:item_name` component is not present, every item now contains the `minecraft:item_name` component. | ||
|
||
Because of this, you must **manually set registry keys in the settings of every block and item**. Failure to do so will result in crashes such as: | ||
|
||
- `NullPointerException: Block id not set` | ||
- `NullPointerException: Item id not set` | ||
|
||
Both settings classes provide a simple method which should be called for every item or block with their respective registry key: | ||
|
||
```java | ||
Identifier id = Identifier.of("mymod", "test_item"); | ||
RegistryKey<Item> key = RegistryKey.of(RegistryKeys.ITEM, id); | ||
|
||
Item.Settings settings = new Item.Settings() | ||
// If your item is based on a block | ||
.useBlockPrefixedTranslationKey() | ||
.registryKey(key); | ||
|
||
Registry.register(Registries.ITEM, key, new Item(settings)); | ||
``` | ||
```java | ||
Identifier id = Identifier.of("mymod", "test_block"); | ||
RegistryKey<Block> key = RegistryKey.of(RegistryKeys.BLOCK, id); | ||
|
||
Block.Settings settings = new Block.Settings() | ||
.registryKey(key); | ||
|
||
Registry.register(Registries.BLOCK, key, new Block(settings)); | ||
``` | ||
|
||
Make sure to call the `Item.Settings#useBlockPrefixedTranslationKey` method for block items so that they use the `block.<namespace>.<path>` translation key format. | ||
|
||
This change affects the following traits: | ||
|
||
- Item names (`minecraft:item_name` component) | ||
- Item models (`minecraft:item_model` component) | ||
- Block models | ||
- Block loot table key | ||
|
||
Some traits, such as the cooldown group of items with cooldowns, still dynamically look up a registry key, but this pattern should be avoided as much as possible. | ||
|
||
`Block#getLootTableKey` now returns `Optional<RegistryKey>`. A block without a corresponding loot table now returns an empty optional instead of the `minecraft:empty` loot table registry key. | ||
|
||
In Fabric API, the previously-deprecated `FabricBlockSettings` class was removed. Use the vanilla `AbstractBlock.Settings` class instead. | ||
|
||
### Furnace fuels | ||
|
||
Furnace fuels are now registered through an event, which allows access to new parameters: | ||
|
||
```diff | ||
- FuelRegistry.INSTANCE.add(ModItems.TEST_ITEM, 50); | ||
+ FuelRegistryEvents.BUILD.register((builder, context) -> { | ||
+ builder.add(ModItems.TEST_ITEM, context.baseSmeltTime() / 4); | ||
+ }); | ||
``` | ||
|
||
The base smelt time can be used to express a fuel's smelt time in terms of a ratio. The default base smelt time is 200 ticks, or 10 seconds. | ||
|
||
### Entities | ||
|
||
`EntityType` received a registry key change similar to the block and item one described above. When building an `EntityType`, pass a `RegistryKey` for the entity type. The no-argument version of the `EntityType.Builder#build` method, injected by `FabricEntityTypeBuilder`, has been removed. For example: | ||
|
||
```java | ||
Identifier id = Identifier.of("mymod", "test_entity_type"); | ||
RegistryKey<EntityType<?>> key = RegistryKey.of(RegistryKeys.ENTITY_TYPE, id); | ||
|
||
EntityType<TestEntity> entityType = EntityType.Builder.<TestEntity>create(TestEntity::new, SpawnGroup.MISC) | ||
.build(key); | ||
|
||
Registry.register(Registries.ENTITY_TYPE, key, entityType); | ||
``` | ||
|
||
Mob conversion (such as zombie villager curing or slimes splitting on death) was overhauled. The exact behavior of conversion is now handled by methods implemented by values of the `EntityConversionType` enum. When using the `MobEntity#convertTo` method to convert a mob, an `EntityConversionContext` is now required. This context is also now passed to Fabric API's `ServerLivingEntityEvents#MOB_CONVERSION` event. | ||
When creating an entity, a spawn reason is now required: | ||
```diff | ||
- Entity pig = EntityType.PIG.create(overworld); | ||
+ Entity pig = EntityType.PIG.create(overworld, SpawnReason.SPAWN_ITEM_USE); | ||
``` | ||
The prefixes of attributes in `EntityAttributes`, like `GENERIC`, have been dropped. This matches a change in the identifiers of attributes: | ||
```diff | ||
- public static final RegistryEntry<EntityAttribute> GENERIC_ATTACK_KNOCKBACK = register( | ||
- "generic.attack_knockback", | ||
- new ClampedEntityAttribute("attribute.name.generic.attack_knockback", 0, 0, 5) | ||
); | ||
+ public static final RegistryEntry<EntityAttribute> ATTACK_KNOCKBACK = register( | ||
"attack_knockback", | ||
new ClampedEntityAttribute("attribute.name.attack_knockback", 0, 0, 5) | ||
); | ||
``` | ||
### Data generation | ||
A recipe provider must now override `getRecipeGenerator` instead of `generate`. The new method takes the registries and `exporter`, and returns a new instance of `RecipeGenerator` that actually generates the recipes. | ||
```diff | ||
- public void generate(RecipeExporter exporter) { | ||
- offerPlanksRecipe2(exporter, SIMPLE_BLOCK, ItemTags.ACACIA_LOGS, 1); | ||
+ protected RecipeGenerator getRecipeGenerator(RegistryWrapper.WrapperLookup registries, RecipeExporter exporter) { | ||
+ return new RecipeGenerator(registries, exporter) { | ||
+ @Override | ||
+ public void generate() { | ||
+ offerPlanksRecipe2(SIMPLE_BLOCK, ItemTags.ACACIA_LOGS, 1); | ||
``` | ||
### ActionResult | ||
Previously, action results have been represented in several ways, including the `ActionResult`, `ItemActionResult`, and `TypedActionResult` classes. In Minecraft 1.21.2, these classes have been merged into a single `ActionResult` class, which provides direct replacements for the previous methods for all three classes: | ||
Old | New | ||
--- | --- | ||
`ActionResult.success(world.isClient())` | `ActionResult.SUCCESS` | ||
`TypedActionResult.pass(stack)` | `ActionResult.PASS` | ||
`TypedActionResult.fail(stack)` | `ActionResult.FAIL` | ||
`TypedActionResult.success(stack, world.isClient())` | `ActionResult.SUCCESS` | ||
`TypedActionResult.consume(stack)` | `ActionResult.CONSUME` | ||
If an action replaces the hand stack with another instance of `ItemStack`, then it should be marked with the `ActionResult#withNewHandStack` method. For example, an `Item#use` implementation that replaces the hand stack might be: | ||
```java | ||
public ActionResult use(World world, PlayerEntity user, Hand hand) { | ||
ItemStack stack = user.getStackInHand(hand); | ||
if (stack.getCount() > 16) { | ||
ItemStack newStack = new ItemStack(Items.BLAZE_ROD, 16); | ||
return ActionResult.SUCCESS.withNewHandStack(newStack); | ||
} | ||
return ActionResult.PASS; | ||
} | ||
``` | ||
On the other hand, if the `ItemStack` instance for the hand stack is the same as the one provided to an interaction method such as `Item#use`, the `ActionResult#withNewHandStack` method should not be called. | ||
This change affects all places where `TypedActionResult` and `ItemActionResult` were previously used in Minecraft's code. In Fabric API, the `UseItemCallback` event in the Events Interaction module now returns `ActionResult` instead of `TypedActionResult<ItemStack>`. | ||
|
||
### Item components | ||
Because elytra behavior is now controlled by a new item component, `minecraft:glider`, `FabricElytraItem` was removed. Add the component to your elytra item instead. | ||
|
||
### Block entities | ||
|
||
In Minecraft 1.21.1 (released in August), a change was made that required mods to add all supported blocks to block entities. For example, a mod with a new sign block must add the block to `BlockEntityType#SIGN`: | ||
|
||
```java | ||
BlockEntityType.SIGN.addSupportedBlock(ModBlocks.TEAL_SIGN); | ||
``` | ||
|
||
In Minecraft 1.21.2, block entity types are no longer constructed using builders. Therefore, `FabricBlockEntityType.Builder` was removed, while `FabricBlockEntityTypeBuilder` is no longer deprecated. | ||
|
||
### Registries | ||
|
||
`Registry` now implements `RegistryEntryLookup`. This resulted in several name changes. To query a `RegistryEntry` from `RegistryKey`, use `getOptional` or `getOrThrow`. (Same applies to `RegistryEntryList` from `TagKey`.) If you want to query the registry value, use `getValueOrThrow`. See the table below for all changes. | ||
|
||
| Old | New | | ||
|----------------|--------------------| | ||
| `getEntry` | `getOptional` | | ||
| `entryOf` | `getOrThrow` | | ||
| `getOrThrow` | `getValueOrThrow` | | ||
| `getOrEmpty` | `getOptionalValue` | | ||
| `getEntryList` | `getOptional` | | ||
|
||
Similarly, `DynamicRegistryManager#get` and `RegistryWrapper.WrapperLookup#getWrapperOrThrow` has been renamed to `getOrThrow`. `getOptionalWrapper` was renamed tp `getOptional`. | ||
|
||
### Rendering | ||
#### Entity rendering | ||
Entity rendering has received a large refactor that decouples the `Entity` instance from its respective rendering calls. `EntityRenderer` now has an additional type parameter, `S extends EntityRenderState`, which represents a 'render state', which is a mutable class containing only the parameters of the entity that are used in rendering. | ||
|
||
Previously, renderer methods accessed the entity instance directly. However, accessing entity information now happens in three steps. | ||
|
||
First, the `EntityRenderer#createRenderState` method is called to construct an instance of `S` for the given entity with placeholder values: | ||
|
||
```java | ||
public T createRenderState() { | ||
return new T(); | ||
} | ||
``` | ||
|
||
Next, the `EntityRenderer#updateRenderState` method performs the operation of copying information from the entity to its render state: | ||
|
||
```java | ||
public void updateRenderState(T entity, S state, float tickDelta) { | ||
super.updateRenderState(entity, state, tickDelta); | ||
|
||
// Example: entity has an 'is saddled' field | ||
state.isSaddled = entity.isSaddled(); | ||
} | ||
``` | ||
|
||
Finally, the `EntityRenderer#render` method (as well as other renderer methods) accesses information from the entity's render state: | ||
```java | ||
public void render(S state, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { | ||
super.render(state, matrices, vertexConsumers, light); | ||
if (state.isSaddled) { | ||
// Render the saddle | ||
} | ||
} | ||
``` | ||
#### Shaders | ||
In Fabric Rendering API, `CoreShaderRegistrationCallback` was removed. Vanilla resource pack now allows loading modded core shaders. | ||
#### Other changes | ||
`WorldRenderer` methods for rendering certain vertices (like a box) were transferred to `VertexRendering`. | ||
<!-- TODO Shader changes. Models. --> | ||
### Recipes | ||
The recipe system was reworked. To summerize: | ||
- Recipes are now identified using `RegistryKey<? extends Recipe>`, not `Identifier`. | ||
- `Recipe` and the recipe ID is now server-side only. It cannot be accessed from the client. | ||
- Instead, clients receive `RecipeDisplayEntry`. It contains all information needed to display and run the recipe book. Recipes are identified using an integer (`NetworkRecipeId`) on the client. A recipe can have multiple display entries. | ||
- `IngredientPlacement` controls the placement of ingredients on the crafting table, while `RecipeMatcher` handles recipe matching. | ||
`Ingredient` is now internally a list of items, not item stacks. | ||
In Fabric API, `CustomIngredientSerializer#getCodec`: `allowEmpty` param removed, empty now always disallowed. | ||
### Biome | ||
Water cave carvers (which, before 1.18, were seen in seabeds) were removed, along with `GenerationStep.Carver`. | ||
In Fabric Biome API, biome modification methods like `addCarver` and `removeCarver` no longer takes `GenerationStep.Carver` argument. | ||
### Profiler | ||
Profiles are now accessed using `Profilers#get`. | ||
```diff | ||
- world.getProfiler().push("tinyPotato"); | ||
+ Profilers.get().push("tinyPotato"); | ||
``` | ||
### Loot tables | ||
`LootTables#EMPTY` was removed. The game uses `Optional` to mark the lack of loot tables. | ||
Some loot context-related logics are now shared with recipes, resulting in name changes. `LootContextParameter` is now `ContextParameter`, and `LootContextType` is now `ContextType`. | ||
### Yarn renames | ||
*This section only affects those using the Yarn mapping.* | ||
As part of regular Yarn maintainace, the following changes were made. These should be a simple replacement: | ||
- `ModelTransformationMode` is transferred to `net.minecraft.item`. | ||
- `RealmsLoadingWidget` is renamed to `LoadingWidget` and transferred to `client.gui.widget`. | ||
- Several `Brain` and `Task`-related names: see [the pull request](https://github.com/FabricMC/yarn/pull/3992) for details. | ||
- `registryLookupFuture` is renamed to `registriesFuture` in several locations. | ||
- `Codecs#NONNEGATIVE_INT` is renamed to `NON_NEGATIVE_INT`. | ||
- `QUATERNIONF` and `VECTOR3F` are renamed to `QUATERNION_F` and `VECTOR_3F`. | ||
- `Screen#initTabNavigation` is renamed to `refreshWidgetPositions`. | ||
- `ComponentMapImpl` is renamed to `MergedComponentMap`. | ||
- `ContainerComponentModifier#create` is renamed to `apply`. | ||
- `ItemStack#encode` is renamed to `toNbt`. |