# Minecraft 1.21.1 -> 1.21.2 模组迁移入门文档

本文档是一个高层次、非详尽的概述，介绍如何将您的模组从 1.21.1 迁移到 1.21.2。本文不涉及任何特定的模组加载器，只关注原版类的变更。所有提供的名称均使用官方的 Mojang 映射。

本入门文档采用 [知识共享署名 4.0 国际许可协议](http://creativecommons.org/licenses/by/4.0/) 授权，因此您可以自由地将其用作参考，并请留下链接以便其他读者查阅。

如果存在任何不正确或缺失的信息，请在本仓库提交 issue，或在 Neoforged Discord 服务器中 @ChampionAsh5357。

## 资源包变更

原版中有许多面向用户的变更为未在下面讨论，但这些变更可能与模组制作者相关。您可以在 [Misode 的版本更新日志](https://misode.github.io/versions/?id=1.21.2&tab=changelog) 中找到它们的列表。

## 持有者集 过渡

许多之前使用 `TagKey` 或原始注册表对象的方法已被直接的 `HolderSet` 对象取代。`HolderSet` 本质上是一个注册表对象引用的列表，游戏可以根据需要动态更新和管理它。实际上有两种 `HolderSet`：直接和命名。命名的 `HolderSet` 是游戏中标签的对象表示。之所以称为命名集，是因为 `HolderSet` 通过标签名称引用。而直接的 `HolderSet` 是通过 `HolderSet#direct` 创建的，它作为一个内联的值列表。当不需要定义单独对象来构造某个值时，这些很有用。

JSON 示例：
```json5
// HolderSet#direct 包含一个元素
{
    "holder_set": "minecraft:apple"
}

// HolderSet#direct 包含多个元素
{
    "holder_set": [
        "minecraft:apple",
        "minecraft:stick"
    ]
}

// HolderSet 引用（标签）
{
    "holder_set": "#minecraft:planks"
}
```

通常，除了在提供者生成期间，您永远不应该在代码中构造持有者集。每种集类型都有不同的构造方法。

首先，要处理 `Holder` 或 `HolderSet`，您需要通过 `Registry` 访问静态注册表实例，或者通过 `HolderGetter` 访问数据包注册表。`HolderGetter` 可以在数据包注册表生成期间从 `BootstrapContext#lookup` 获得，或者在生成期间或游戏过程中的 `MinecraftServer#registryAccess` 从 `HolderLookup$Provider#lookupOrThrow` 获得。

一旦可用，对于直接的 `HolderSet`，您需要获取注册表对象的 `Holder` 形式。对于静态注册表，通过 `Registry#wrapAsHolder` 完成。对于数据包注册表，通过 `HolderGetter#getOrThrow` 完成。

```java
// 物品的直接 HolderSet
HolderSet<Item> items = HolderSet.direct(BuiltInRegistries.ITEM.wrapAsHolder(Items.APPLE));

// 配置功能的直接 HolderSet
// 假设我们可以访问 HolderGetter<ConfiguredFeature<?, ?>> 注册表
Holderset<ConfiguredFeature<?, ?>> features = HolderSet.direct(registry.getOrThrow(OreFeatures.ORE_IRON));
```

对于命名的 `HolderSet`，过程类似。对于静态和动态注册表，都调用 `HolderGetter#getOrThrow`。

```java
// 物品的命名 HolderSet
HolderSet<Item> items = BuiltInRegistries.ITEM.getOrThrow(ItemTags.PLANKS);

// 生物群系的命名 HolderSet
// 假设我们可以访问 HolderGetter<Biome> 注册表
Holderset<Biome> biomes = registry.getOrThrow(BiomeTags.IS_OCEAN);
```

由于这些变更遍及整个代码库，它们将在更相关的子章节中列出。

## GUI 渲染类型

`GuiGraphics` 中的 GUI 渲染方法现在接受一个 `Function<ResourceLocation, RenderType>` 来确定如何渲染图像。此外，`blit` 方法现在需要指定 PNG 的大小。

```java
// 对于某个 GuiGraphics graphics
graphics.blit(
    // 如何渲染纹理
    RenderType::guiTextured,
    // 之前的纹理参数
    ...,
    // 要使用的 PNG 大小
    256, 256);
```

这意味着那些提供设置纹理或其他可在着色器中指定属性的辅助方法已被移除。

- `com.mojang.blaze3d.pipeline.RenderTarget#blitToScreen(int, int, boolean)` -> `blitAndBlendToScreen`
- `net.minecraft.client.gui.GuiGraphics`
    - `drawManaged` 已移除
    - `setColor` 已移除 - 现在是 `blit` 和 `blitSprite` 方法中的一个参数
    - `blit(int, int, int, int, int, TextureAtlasSprite, *)` 已移除
    - `bufferSource` -> `drawSpecial`，不是一对一，因为该方法接受一个 `MultiBufferSource` 的消费者，并结束当前批次，而不是仅仅返回 `MultiBufferSource`
- `net.minecraft.client.gui.components.PlayerFaceRenderer`
    - 除 `draw(GuiGraphics, PlayerSkin, int, int, int)` 之外的所有 `draw` 方法都接受一个额外的 `int` 参数，用于定义颜色
- `net.minecraft.client.renderer.RenderType`
        - `guiTexturedOverlay` - 获取叠加在游戏屏幕上的图像的渲染类型。
        - `guiOpaqueTexturedBackground` - 获取应用于菜单背景的 GUI 纹理的渲染类型。
        - `guiNauseaOverlay` - 获取恶心覆盖层的渲染类型。
        - `guiTextured` - 获取 GUI 菜单内图像的渲染类型。
- `net.minecraft.client.resources.metadata.gui.GuiSpriteScaling$NineSlice` 现在接受一个布尔值，表示纹理的中心部分是否应拉伸以适应大小。

## 着色器重写

着色器的内部实现已被大量重写。

### 着色器文件

主要变更是定义的采样器和后期着色器。

`DiffuseSampler` 和 `DiffuseDepthSampler` 已根据应用目标被赋予新名称：`InSampler`、`MainSampler` 和 `MainDepthSampler`。`InSampler` 用于除 `transparency` 程序着色器之外的所有场景。

```json5
// 在某个着色器 JSON 中
{
    "samplers": [
        { "name": "MainSampler" },
        // ...
    ]
}
```

在后处理效果着色器中，它们已被完全改变。有关变更的完整分析，请参见 `PostChainConfig`，但总的来说，所有目标现在都是对象的键，所有通道输入和过滤器现在是采样器输入的列表。如下所示：

```json5
// 旧的后处理效果着色器 JSON
// 在 assets/<namespace>/shaders/post 中
{
    "targets": [
        "swap"
    ],
    "passes": [
        {
            "name": "invert",
            "intarget": "minecraft:main",
            "outtarget": "swap",
            "use_linear_filter": true,
            "uniforms": [
                {
                    "name": "InverseAmount",
                    "values": [ 0.8 ]
                }
            ]
        },
        {
            "name": "blit",
            "intarget": "swap",
            "outtarget": "minecraft:main"
        }
    ]
}

// 新的后处理 JSON
// 在 assets/<namespace>/post_effect 中
{
    "targets": {
        "swap": {} // swap 现在是一个目标对象（除非另有指定，否则为全屏）
    },
    "passes": [
        {
            // 要应用的程序名称（之前为 'name'）
            // assets/minecraft/shaders/post/invert.json
            "program": "minecraft:post/invert",
            // inputs 现在是一个列表
            "inputs": [
                {
                    // 目标是 InSampler
                    // 采样器必须在程序着色器 JSON 中可用
                    "sampler_name": "In",
                    // 从主屏幕读取（之前为 'intarget'）
                    "target": "minecraft:main",
                    // 使用 GL_LINEAR（之前为 'use_linear_filter'）
                    "bilinear": true
                }
            ],
            // 写入 swap 目标（之前为 'outtarget'）
            "output": "swap",
            "uniforms": [
                {
                    "name": "InverseAmount",
                    "values": [ 0.8 ]
                }
            ]
        },
        {
            "program": "minecraft:post/blit",
            "inputs": [
                {
                    "sampler_name": "In",
                    "target": "swap"
                }
            ],
            "output": "minecraft:main"
        }
    ]
}
```

### 着色器程序

所有着色器，无论它们在何处使用（作为程序或后处理效果的一部分），都在 `assets/<namespace>/shaders` 中有一个 JSON。该 JSON 定义了着色器将使用的所有内容，由 `ShaderProgramConfig` 定义。主要增加是对 `ResourceLocation` 相对引用的更改，以及在加载期间动态添加 `defines` 头。

```json5
// 对于某个 assets/my_mod/shaders/my_shader.json
{
    // 指向 assets/my_mod/shaders/my_shader.vsh（之前为 'my_shader'，无 id 指定）
    "vertex": "my_mod:my_shader",
    // 指向 assets/my_mod/shaders/my_shader.fsh（之前为 'my_shader'，无 id 指定）
    "fragment": "my_mod:my_shader",
    // 向着色器添加 '#define' 头
    "defines": {
        // #define <key> <value>
        "values": {
            "ALPHA_CUTOUT": "0.1"
        },
        // #define flag
        "flags": [
            "NO_OVERLAY"
        ]
    },
    // 要在着色器中使用的采样器统一变量列表
    // 有 12 个纹理采样器统一变量 Sampler0-Sampler11，但通常只提供 Sampler0
    // 此外，对于后处理着色器，有动态的 '*Sampler'，它们被绑定以读取指定的目标或 'minecraft:main'
    "samplers": [
        { "name": "Sampler0" }
    ],
    // 可在着色器中访问的统一变量列表
    // 可用统一变量的列表可以在 CompiledShaderProgram#setUniforms 中找到
    "uniforms": [
        { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
        { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
        { "name": "ModelOffset", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] },
        { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }
    ]
}
```

```glsl
// 对于某个 assets/my_mod/shaders/my_shader.vsh（顶点着色器）

// GLSL 版本
#version 150

// 导入 Mojang GLSL 文件
// 位于 assets/<namespace>/shaders/include/<path>
#moj_import <minecraft:light.glsl>

// 注入定义（可以使用 'ALPHA_CUTOUT' 和 'NO_OVERLAY'）

// 由下面传递给 ShaderProgram 的 VertexFormat 定义
in vec3 Position; // vec3 浮点数
in vec4 Color; // vec4 无符号字节（0-255）

// 由 JSON 定义的采样器
uniform sampler2D Sampler0;

// 由 JSON 提供的统一变量
uniform mat4 ModelViewMat;
uniform mat4 ProjMat;
uniform vec3 ModelOffset;

// 输出到片段着色器的值
out float vertexDistance;
out vec4 vertexColor;
out vec2 texCoord0;

void main() {
    // 在此处设置输出值
}
```

```glsl
// 对于某个 assets/my_mod/shaders/my_shader.fsh（片段着色器）

// GLSL 版本
#version 150

// 导入 Mojang GLSL 文件
// 位于 assets/<namespace>/shaders/include/<path>
#moj_import <minecraft:fog.glsl>

// 注入定义（可以使用 'ALPHA_CUTOUT' 和 'NO_OVERLAY'）

// 由上面顶点着色器的输出定义
in float vertexDistance;
in vec4 vertexColor;
in vec2 texCoord0;

// 由 JSON 定义的采样器
uniform sampler2D Sampler0;

// 由 JSON 提供的统一变量
uniform vec4 ColorModulator;

// 输出到帧缓冲区的值（像素的颜色）
out vec4 fragColor;

void main() {
    // 在此处设置输出值
}
```

在代码方面，着色器在内部存储为 `ShaderProgram` 或 `CompiledShaderProgram`。`ShaderProgram` 表示标识符，而 `CompiledShaderProgram` 表示要运行的着色器本身。两者通过 `ShaderManager` 链接在一起。

除非指定为核心着色器，否则着色器程序是动态编译的。这通过将 `ShaderProgram` 注册到 `CoreShaders#PROGRAMS` 来完成。

```java
// 访问 List<ShaderProgram> PROGRAMS
ShaderProgram MY_SHADER = new ShaderProgram(
    // 指向 assets/my_mod/shaders/my_shader.json
    ResourceLocation.fromNamespaceAndPath("my_mod", "my_shader"),
    // 传入着色器使用的顶点格式
    DefaultVertexFormat.POSITION_COLOR,
    // 列出 '#define' 值和标志
    // 值：'#define <key> <value>'
    // 标志：'#define <flag>'
    ShaderDefines.EMPTY
)
```

然后通过调用 `RenderSystem#setShader` 并传入相应的 `ShaderProgram` 来设置着色器程序。实际上，所有对 `GameRenderer#get*Shader` 的引用都应替换为 `ShaderProgram` 引用。

```java
// 在某个渲染方法中
RenderSystem.setShader(MY_SHADER);

// 为 RenderType 创建新的 ShaderStateShard
ShaderStateShard MY_SHARD = new ShaderStateShard(MY_SHADER);
```

- `com.mojang.blaze3d.ProjectionType` - 一个枚举，包含投影矩阵应如何渲染的逻辑。
- `com.mojang.blaze3d.buffers`
    - `BufferType` - 一个枚举，指定 GL 目标缓冲区类型。
    - `GpuBuffer` - 围绕 GL 缓冲区调用的包装器，用于处理屏幕渲染。
    - `GpuFence` - 用于管理 GPU 围栏同步状态的句柄。
- `com.mojang.blaze3d.platform.GlStateManager`
    - `glShaderSource` 现在接受一个 `String` 而不是 `List<String>`
    - `_glMapBufferRange` - 委托给 `GL30#glMapBufferRange`。
    - `_glFenceSync` - 委托给 `GL32#glFenceSync`。
    - `_glClientWaitSync` - 委托给 `GL32#glClientWaitSync`。
    - `_glDeleteSync` - 委托给 `GL32#glDeleteSync`。
    - `_glBuffserSubData` - 委托给 `GL15#glBufferSubData`。
- `com.mojang.blaze3d.preprocessor.GlslPreprocessor#injectDefines` - 将任何定义的源注入到加载的 `.*sh` 文件的顶部。
- `com.mojang.blaze3d.shaders`
    - `BlendMode`、`Effect`、`EffectProgram`、`Program`、`ProgramManager`、`Shader` 已被整合到 `CompiledShader` 中
    - `Unform` 不再接受 `Shader`
        - `glGetAttribLocation` 已移除
        - `glBindAttribLocation` -> `VertexFormat#bindAttributes`
        - `setFromConfig` - 根据另一个统一配置的值和计数设置统一参数。
- `com.mojang.blaze3d.systems.RenderSystem`
    - `setShader` 现在接受 `CompiledShaderProgram` 或 `ShaderProgram`
    - `clearShader` - 清除当前系统着色器。
    - `runAsFancy` 已移除，由 `LevelRenderer#getTransparencyChain` 内部处理
    - `setProjectionMatrix` 现在接受一个 `ProjectionType` 而不仅仅是 `VertexSorting`
    - `getVertexSorting` -> `getProjectionType`；不是一对一，但 `VertexSorting` 可在 `ProjectionType` 上访问
- `com.mojang.blaze3d.vertex.VertexBuffer`
    - `drawWithShader` 在传入 `null` 的 `CompiledShaderProgram` 时将成为空操作
    - `$Usage` -> `com.mojang.blaze3d.buffers.BufferUsage`
- `net.minecraft.client.Minecraft#getShaderManager` - 返回管理所有着色器和后处理效果的管理器。
- `net.minecract.client.renderer`
    - `EffectInstance` 类已移除，在大多数情况下被 `CompiledShaderProgram` 取代
    - `GameRenderer`
        - `get*Shader` -> `CoreShaders#*`
        - `shutdownEffect` -> `clearPostEffect`
        - `createReloadListener` -> `ShaderManager`
        - `currentEffect` -> `currentPostEffect`
    - `ItemBlockRenderTypes#getRenderType` 不再接受一个表示是否使用半透明渲染类型的布尔值
    - `ShaderInstance` -> `CompiledShaderProgram`
        - `CHUNK_OFFSET` -> `MODEL_OFFSET`
            - JSON 着色器：`ChunkOffset` -> `ModelOffset`
        - `getUniformConfig` - 返回给定名称的统一变量的配置。
    - `LevelRenderer#graphicsChanged` 已移除，由 `LevelRenderer#getTransparencyChain` 内部处理
    - `PostChainConfig` - 表示后处理效果着色器 JSON 如何构建的配置。
    - `PostPass` 现在接受代表输出目标的 `ResourceLocation` 而不是输入和输出 `RenderTarget` 或 `boolean` 过滤模式，要使用的 `CompiledShaderProgram` 而不是 `ResourceProvider`，以及着色器要使用的一组统一变量
        - 不再实现 `AutoCloseable`
        - `addToFrame` 不再接受 `float` 时间
        - `getEffect` -> `getShader`
        - `addAuxAsset` -> `addInput`
        - `process` -> `addToFrame`
        - `$Input` - 表示后处理效果着色器的输入。
        - `$TargetInput` - 来自 `RenderTarget` 的输入。
        - `$TextureInput` - 来自纹理的输入。
    - `PostChain` 构造函数现在通过 `load` 创建
        - 不再实现 `AutoCloseable`
        - `MAIN_RENDER_TARGET` 现在是公开的
        - `getName` 已移除，被 `ShaderProgram#configId` 取代
        - `process` 不再接受 `DeltaTracker`
        - `$TargetBundle` - 处理链中资源句柄的获取和替换。
    - `RenderType`
        - `entityTranslucentCull`、`entityGlintDirect` 已移除
        - `armorTranslucent` - 一种渲染类型，用于渲染可以具有半透明纹理的盔甲。
    - `ShaderDefines` - 着色器用作常量的定义值和标志。
    - `ShaderManager` - 加载着色器的资源监听器。
    - `ShaderProgram` - 着色器的标识符。
    - `ShaderProgramConfig` - 程序着色器 JSON 的定义。
    - `Sheets#translucentCullBlockSheet` 已移除
    - `SkyRenderer` 现在实现 `AutoCloseable`
- `net.minecraft.client.renderer.entity.ItemRenderer`
    - `getFoilBufferDirect` 已移除，被 `getFoilBuffer` 取代
    - `ITEM_COUNT_BLIT_OFFSET` -> `ITEM_DECORATION_BLIT_OFFSET`

## 实体渲染状态

由于 `EntityRenderState` 的加入，实体模型和渲染器几乎完全重做。`EntityRenderState` 本质上是数据对象类，只公开渲染实体所需的计算信息。例如，`Llama` 不需要知道它的背包里有什么，只需要知道它有一个箱子要在层中渲染。

首先，您需要选择要使用的 `EntityRenderState`，或者如果需要将额外信息传递给渲染器，则使用子类创建一个。最常见的子类状态是 `EntityRenderState` 或用于活体的 `LivingEntityRenderState`。这些字段应该是可变的，因为状态类只为每个渲染器创建一次。

```java
// 假设 MyEntity 继承 LivingEntity
public class MyEntityRenderState extends LivingEntityRenderState {
    // 字段示例
    boolean hasExampleData;
}
```

然后，您创建将渲染实体的 `EntityModel`。`EntityModel` 有一个泛型，接受 `EntityRenderState`，并在其父类中接受 `ModelPart` 根，以及可选的 `RenderType` 工厂。默认情况下没有需要实现的方法；但是，如果您需要设置任何类型的模型运动，您需要覆盖 `setupAnim`，它使用渲染状态修改 `ModelPart` 的可变字段。如果您的模型没有任何动画，则可以使用 `Model$Simple` 实现。它不需要实现任何东西。

```java
public class MyEntityModel extends EntityModel<MyEntityRenderState> {

    public MyEntityModel(ModelPart root) {
        super(root);
        // ...
    }

    @Override
    public void setupAnim(MyEntityRenderState state) {
        // 调用 resetPose 以及父类所做的任何其他变换
        super.setupAnim(state); 

        // 在此处对模型部件执行变换
    }
}
```

`EntityModel` 还有三个来自 `Model` 子类的 `final` 方法：`root`，获取根 `ModelPart`；`allParts`，返回所有 `ModelPart` 的扁平列表；以及 `resetPose`，将 `ModelPart` 恢复到其默认状态。

`LayerDefinition`、`MeshDefinition`、`PartDefinition` 和 `CubeDeformation` 在 `LayerDefinitions` 中 `ModelLayerLocation` -> `LayerDefinition` 映射的实现和构造保持不变。

模型变换呢？例如，实体的幼年版本，或者模型完全切换的情况？在这些情况下，为每个模型注册一个单独的层定义。例如，Llama 将有一个用于主 Llama 模型的模型层、幼年模型层、成年和幼年装饰层，以及最后用于唾沫的层。由于模型通常彼此相似，只有轻微的变换，`LayerDefinition` 添加了一个新方法来接受 `MeshTransformer`。`MeshTransformer` 基本上是 `MeshDefinition` 上的一元运算符。对于幼年模型，提供了一个 `BabyModelTransform` 网格变换器，可以通过 `LayerDefinition#apply` 应用。

```java
public class MyEntityModel extends EntityModel<MyEntityRenderState> {
    public static final MeshTransformer BABY_TRANSFORMS = ...;

    public static LayerDefinition create() {
        // ...
    }
}

// 在注册模型层的地方
ModelLayerLocation MY_ENTITY = layers.register("examplemod:my_entity");
ModelLayerLocation MY_ENTITY_BABY = layers.register("examplemod:my_entity_baby");

// 在注册层定义的地方
defns.register(MY_ENTITY, MyEntityModel.create());
defns.register(MY_ENTITY_BABY, MyEntityModel.create().apply(MyEntityModel.BABY_TRANSFORMS));
```

但是模型如何知道使用哪个渲染状态？这就是 `EntityRenderer` 的作用。`EntityRenderer` 有两个泛型：`Entity` 的类型和 `EntityRenderState` 的类型。`EntityRenderer` 接受一个 `Context` 对象，与之前类似。此外，需要实现 `getTextureLocation`，不过这次它接受渲染状态而不是实体。需要实现/覆盖的新方法是 `createRenderState` 和 `extractRenderState`。`createRenderState` 构造默认渲染状态对象。而 `extractRenderState` 则填充当前正在渲染的实体的渲染状态。如果您没有使用现有的渲染状态类，则需要覆盖 `extractRenderState`。

当然，还有 `EntityRenderer` 的子类。首先，有 `LivingEntityRenderer`。它有一个额外的泛型，即正在渲染的 `EntityModel`，并在构造函数中接受该值以及阴影半径。这个渲染器还接受 `RenderLayer`，如果您通过渲染状态访问之前的参数，这些层基本保持不变。然后是 `MobRenderer`，所有实体都扩展它。最后是 `AgeableMobRenderer`，它接受两个模型——成年和幼年——并根据 `LivingEntityRenderState#isBaby` 决定渲染哪个。如果实体有幼年形态，应该使用 `AgeableMobRenderer` 配合 `BabyModelTransform`。否则，您很可能使用 `MobRenderer` 或 `EntityRenderer`。

```java
public class MyEntityRenderer extends AgeableMobRenderer<MyEntity, MyEntityRenderState, MyEntityModel> {

    public MyEntityRenderer(EntityRendererProvider.Context ctx) {
        super(
            ctx,
            new MyEntityModel(ctx.bakeLayer(MY_ENTITY)), // 成年模型
            new MyEntityModel(ctx.bakeLayer(MY_ENTITY_BABY)), // 幼年模型
            0.7f // 阴影半径
        );

        // ...
    }

    @Override
    public ResourceLocation getTextureLocation(MyEntityRenderState state) {
        // 在此处返回实体纹理
    }

    @Override
    public MyEntityRenderState createRenderState() {
        // 构造可重用的状态
        return new MyEntityRenderState();
    }

    @Override
    public void extractRenderState(MyEntity entity, MyEntityRenderState state, float partialTick) {
        // 设置活体实体和实体渲染状态信息
        super.extractRenderState(entity, state, partialTick);
        // 设置我们自己的变量
        state.hasExampleData = entity.hasExampleData();
    }
}

// 在注册实体渲染器的地方
renderers.register(MyEntityTypes.MY_ENTITY, MyEntityRenderer::new);
```

- `net.minecraft.client.model`
    - `AbstractBoatModel` - 一个模型，假设存在 `left_paddle` 和 `right_paddle`，并根据船的划桨时间进行动画。
    - `AgeableHierarchicalModel`、`ColorableAgeableListModel`、`AgeableListModel` -> `BabyModelTransform`
    - `AnimationUtils`
        - `animateCrossbowCharge` 现在接受一个表示充能持续时间的 `float` 和一个表示使用刻数的 `int`，而不是 `LivingEntity`
        - `swingWeaponDown` 现在接受一个 `HumanoidArm` 而不是 `Mob`
    - `BabyModelTransform` - 一种网格变换器，应用模型的幼年缩放形式。
    - `BoatModel`
        - `createPartsBuilder` 已移除
        - `createChildren` -> `addCommonParts`，现在是私有的
        - `createBodyModel` -> `createBoatModel`、`createChestBoatModel`
        - `waterPatch` -> `createWaterPatch`
        - `parts` 已移除
    - `ChestBoatModel` -> `BoatModel#createChestBoatModel`
    - `ChestedHorseModel` 类已移除，现在完全存在于 `LlamaModel` 和 `DonkeyModel` 中
    - `ChestRaftModel` -> `RaftModel#createChestRaftModel`
    - `ColorableHierarchicalModel` 现在存储在单独的 `EntityRenderState` 中
    - `EntityModel`
        - 泛型现在接受 `EntityRenderState`
        - `setupAnim` 只接受 `EntityRenderState` 泛型
        - `prepareMobModel` 已移除
        - `copyPropertiesTo` 已移除，仍然存在于 `HumanoidModel` 中
    - `HierarchicalModel` 类已移除
    - `HumanoidModel#rotLerpRad` -> `Mth#rotLerpRad`
    - `ListModel` 类已移除
    - `Model`
        - `renderToBuffer` 现在是 final 的
        - `root` - 返回根 `ModelPart`。
        - `getAnyDescendantWithName` - 返回根中具有指定名称的第一个后代。
        - `animate` - 给定动画的当前状态和定义，在当前时间和最大时间之间变换模型以播放动画。
        - `animateWalk` - 对模型的行走循环进行动画。
        - `applyStatic` - 将即时动画应用于指定状态。
        - `$Simple` - 构造一个没有额外动画的简单模型。
    - `ModelUtils` 类已移除
    - `ParrotModel#getState` -> `getPose`，现在是公开的
    - `PlayerModel` 不再有泛型
        - `renderEars` -> `PlayerEarsModel`
        - `renderCape` -> `PlayerCapeModel`
        - `getRandomModelPart` -> `getRandomBodyPart`
        - `getArmPose` - 返回玩家给定其渲染状态的手臂姿势。
    - `RaftModel#createBodyModel` -> `createRaftModel`
    - `WardenModel#getTendrilsLayerModelParts`、`getHeartLayerModelParts`、`getBioluminescentLayerModelParts`、`getPulsatingSpotsLayerModelParts` 现在接受 `WardenRenderState`
    - `WaterPatchModel` -> `BoatModel#createWaterPatch` 和 `Model$Simple`
- `net.minecraft.client.model.geom`
    - `ModelLayerLocation` 现在是一个记录
    - `ModelLayers`
        - `createRaftModelName`、`createChestRaftModelName` 已移除
        - `createSignModelName` -> `createStandingSignModelName`、`createWallSignModelName`
        - `createBoatModelName`、`createChestBoatModelName` 已移除
    - `ModelPart`
        - `rotateBy` - 使用给定的 `Quaternionf` 旋转部件。
        - `$Cube#polygons`、`$Polygon`、`$Vertex` 现在是公开的
    - `PartPose` 现在是一个记录
        - `translated` - 平移一个姿势。
        - `withScale`、`scaled` - 缩放一个姿势。
- `net.minecraft.client.model.geom.builders`
    - `LayerDefinition#apply` - 对定义应用网格变换器并返回一个新的。
    - `MeshDefinition#transformed` - 对根姿势应用变换并返回一个新的。
    - `MeshTransformer` - 将现有的 `MeshDefinition` 转换为给定形式。
    - `PartDefinition`
        - `addOrReplaceChild` 现在有一个接受 `PartDefinition` 的重载
        - `clearChild` - 从部件定义中移除子部件。
        - `getChildren` - 获取当前部件的所有子部件。
        - `transformed` - 对当前姿势应用变换并返回一个新的。
- `net.minecraft.client.renderer.entity`
    - `AbstractBoatRenderer` - 一个船渲染器，包含用于船模型和船本身任何附加内容的方法。
    - `AgeableMobRenderer` - 一个接受幼年和成年模型的生物渲染器。
    - `BoatRenderer` 现在接受一个 `ModelLayerLocation` 而不是 `boolean`
    - `EntityRenderDispatcher` 现在接受一个 `MapRenderer`
        - `render` 不再接受实体的 Y 旋转
    - `EntityRenderer` 现在接受 `EntityRenderState` 的泛型
        - `getRenderOffset` 只接受 `EntityRenderState`
        - `getBoundingBoxForCulling` - 返回实体的边界框以确定是否剔除。
        - `affectedByCulling` - 返回实体是否可以被剔除。
        - `render` 只接受渲染状态，以及堆栈、缓冲区源和包光
        - `shouldShowName` 现在接受一个 `double` 表示相机到实体的平方距离
        - `getTextureLocation` 已移除，被移动到使用它的类中，如 `LivingEntityRenderer`
            - 后续的 `getTextureLocation` 实现可能是 protected 或 private
        - `renderNameTag` 现在接受渲染状态而不是实体，并移除了部分刻 `float`
        - `getNameTag` - 从实体获取名称标签。
        - `getShadowRadius` 现在接受渲染状态而不是实体
        - `createRenderState` - 创建渲染状态对象。
        - `extractRenderState` - 将实体中的任何数据读取到渲染状态。
    - `EntityRendererProvider$Context` 接受 `MapRenderer` 而不是 `ItemInHandRenderer`
    - `LivingRenderer`
        - `isShaking` 现在接受渲染状态而不是实体
        - `setupRotations` 现在接受渲染状态而不是实体
        - `getAttackAnim`、`getBob` 现在在渲染状态中
        - `getFlipDegrees` 不再接受实体
        - `getWhiteOverlayProgress` 现在接受渲染状态而不是实体，并且不再接受实体的 Y 旋转
        - `scale` 现在接受渲染状态而不是实体，并且不再接受实体的 Y 旋转
        - `shouldShowName` 现在接受一个 `double` 表示到相机的平方距离
        - `getShadowRadius` 现在接受渲染状态而不是实体
    - `RaftRenderer` - 一个实现 `AbstractBoatRenderer` 的木筏渲染器。
    - `RenderLayerParent#getTextureLocation` 已移除
- `net.minecraft.client.renderer.entity.layers`
    - `EnergySwirlLayer#isPowered` - 返回能量是否被充能。
    - `CustomHeadLayer` 和 `#translateToHead` 接受一个 `CustomHeadLayer$Transforms` 而不是硬编码变换的缩放信息
    - `PlayerItemInHandRenderer` 接受一个 `ItemRenderer` 而不是 `ItemInHandRenderer`
    - `RenderLayer` 接受 `EntityRenderState` 泛型而不是 `Entity` 泛型
        - `coloredCutoutModelCopyLayerRender` 接受一个 `EntityModel`，状态信息捆绑在渲染状态中
        - `renderColoredCutoutModel` 接受非泛型形式的渲染信息，假设为 `LivingEntityRenderState`
        - `getTextureLocation` 已移除，改为直接传递到适当的位置
        - `render` 现在接受渲染状态而不是实体和参数信息
    - `SaddleLayer` 有一个接受幼年模型的构造函数。
    - `SheepFurLayer` -> `SheepWoolLayer`
    - `StuckInBodyLayer` 现在接受要应用卡住对象的模型、卡住对象的纹理以及对象的放置样式
        - `numStuck` 现在接受渲染状态而不是实体
        - `renderStuckItem` 现在是私有的
    - `WardenEmissiveLayer` -> `LivingEntityEmissiveLayer`，一个更通用的实现
- `net.minecraft.client.renderer.entity.player.PlayerRenderer`
    - `renderRightHand`、`renderLeftHand` 现在接受一个 `ResourceLocation` 而不是 `AbstractClientPlayer`，以及一个 `boolean` 表示是否渲染左袖和/或右袖
    - `setupRotations` 现在接受渲染状态而不是实体和参数信息
- `net.minecraft.world.entity`
    - `AnimationState#copyFrom` - 从另一个状态复制动画状态。
    - `Entity`
        - `noCulling` -> `EntityRenderer#affectedByCulling`
        - `getBoundingBoxForCulling` -> `EntityRenderer#getBoundingBoxForCulling`
    - `LerpingModel` 类已移除
    - `PowerableMob` 类已移除

### 模型烘焙

`UnbakedModel` 现在有一个不同的方法来解析任何依赖项。不再获取依赖项并解析父级，而是通过一个称为 `resolveDependencies` 的单一方法完成。该方法接受 `Resolver`。`Resolver` 负责获取 `ResourceLocation` 的 `UnbakedModel`。

```java
// 对于某个 UnbakedModel 实例
public class MyUnbakedModel implements UnbakedModel {

    @Nullable
    protected ResourceLocation parentLocation;
    @Nullable
    protected UnbakedModel parent;
    private final List<ItemOverride> overrides;

    // ...

    @Override
    public void resolveDependencies(UnbakedModel.Resolver resolver) {
        // 获取父模型以进行委托解析
        if (this.parentLocation != null) {
            this.parent = resolver.resolve(this.parentLocation);
        }
    }
}
```

- `net.minecraft.client.renderer.block`
    - `BlockModel#getDependencies`、`resolveParents` -> `resolveDependencies`
    - `BlockModelDefintion` 现在接受一个 `MultiPart$Definition`，不存在接受 `List<BlockModelDefinition>` 的构造函数
        - `fromStream`、`fromJsonElement` 不再接受 `$Context`
        - `getVariants` 已移除
        - `isMultiPart` 已移除
        - `instantiate` -> `MultiPart$Definition#instantiate`
    - `MultiVariant` 现在是一个记录
    - `UnbakedBlockStateModel` - 一个表示方块状态模型的接口，包含一个将具有相同模型的状态分组在一起的单一方法。
    - `VariantSelector` - 用于从模型描述符构建状态定义的工具。
- `net.minecraft.client.renderer.block.model`
    - `BlockModel`
        - `MISSING_MATERIAL` - 缺失方块纹理的材质。
        - `bake` 不再接受 `ModelBaker` 和 `BlockModel`
        - `$LoopException` 类已移除
- `net.minecraft.client.renderer.block.model.multipart.MultiPart` 现在实现 `UnbakedBlockStateModel`
    - `getSelectors` -> `$Definition#selectors`
    - `getMultiVariants` ->` $Definition#getMultiVariants`
- `net.minecraft.client.resources.model`
    - `BakedModel#getOverrides` -> `overrides`，方法默认为空覆盖
    - `BlockStateModelLoader` 只接受缺失的未烘焙模型
        - `loadAllBlockStates` 已移除
        - `definitionLocationToBlockMapper` - 从给定的资源位置获取状态定义
        - `loadBlockStateDefinitions` -> `loadBlockStateDefinitionStack`
        - `getModelGroups` -> `ModelGroupCollector`
        - `$LoadedJson` -> `$LoadedBlockModelDefinition`
        - `$LoadedModel` 现在是公开的
        - `$LoadedModels` - 一个将模型位置映射到已加载模型的记录。
    - `BuiltInModel` 不再接受 `ItemOverrides`
    - `DelegateBakedModel` - 一个将所有逻辑委托给提供的 `BakedModel` 的工具实现
    - `Material#buffer` 接受另一个 `boolean`，用于处理是否应用闪光效果
    - `MissingBlockModel` - 方块的缺失模型。
    - `ModelBaker#getModel` 已移除，`ModelBakery$ModelBakerImpl` 中的实现是私有的
    - `ModelBakery` 只接受顶层模型、所有未烘焙模型和缺失模型
        - `BUILTIN_SLASH` -> `SpecialModels#builtinModelId`
        - `BUILTIN_SLASH_GENERATED` -> `SpecialModels#BUILTIN_GENERATED`
        - `BUILTIN_BLOCK_ENTITY` -> `SpecialModels#BUILTIN_BLOCK_ENTITY`
        - `MISSING_MODEL_LOCATION` -> `MissingBlockModel#LOCATION`
        - `MISSING_MODEL_VARIANT` -> `MissingBlockModel#VARIANT`
        - `GENERATION_MARKER` -> `SpecialModels#GENERATED_MARKER`
        - `BLOCK_ENTITY_MARKER` -> `SpecialModels#BLOCK_ENTITY_MARKER`
        - `getModelGroups` -> `ModelGroupCollector`
    - `ModelDiscovery` - 方块和物品模型的加载器，例如在读取时如何解析它们。
    - `ModelGroupCollector` - 一个方块状态收集器，用于将状态映射到它们关联的方块模型。
    - `ModelResourceLocation#vanilla` 已移除
    - `MultiPartBakedModel` 字段现在从选择器中的第一个模型获取，并且是私有的
        - `$Builder` 类已移除，被 `$Selector` 取代
    - `SimpleBakedModel`、`SimpleBakedModel$Builder` 不再接受 `ItemOverrides`
    - `SpecialModels` - 内置模型的工具。
    - `UnbakedModel`
        - `getDependencies`、`resolveParents` -> `resolveDependencies`
        - `bake` 不再可为 null
        - `$Resolver` - 确定在顶层或覆盖时如何加载未烘焙模型。
    - `WeightedBakedModel` 现在接受一个 `SimpleWeightedRandomList` 而不是 `WeightedEntry` 的列表

## 装备与物品、模型等等

装备和物品经历了重大改革，其中大部分分散在整个文档中。这是一些核心变更，虽然它们很重要，但由于易于更改，不值得详细解释。

### 物品名称和模型

物品名称和模型现在直接通过属性中的 `ITEM_NAME` 和 `ITEM_MODEL` 数据组件设置。默认情况下，这将使用与以前相同的名称和模型位置，但可以通过 `Item$Properties#overrideDescription` 和 `#overrideModel` 设置。`overrideDescription` 接受要使用的翻译键。还有 `useBlockDescriptionPrefix` 和 `useItemDescriptionPrefix` 分别将其更改为默认的方块和物品翻译键。`overrideModel` 接受模型 JSON 的相对 `ResourceLocation`。例如，值 `examplemod:example_item` 将映射到 `examplemod:example_item#inventory` 的 `ModelResourceLocation`。这旨在链接到 `assets/examplemod/models/item/example_item.json` 的模型 JSON。

> 物品模型有一个小特性。如果模组制作者决定在 `inventory` 变体下在该位置加载特殊模型，则相同的键也可以指向 `assets/examplemod/models/example_item.json`。因此，建议避免在根 `models` 和 `models/item` 子目录中使用同名模型名称。

### 可附魔、可修复物品

附魔值和修复物品检查正在被数据组件取代：分别是 `DataComponents#ENCHANTABLE` 和 `DataComponents#REPAIRABLE`。这些可以通过 `Item$Properties#enchantable` 和 `#repairable` 设置。因此，`Item#getEnchantmentValue` 和 `isValidRepairItem` 已移除。

### 鞘翅 -> 滑翔翼

任何物品如果装备了 `DataComponents#GLIDER` 值，都可以像鞘翅一样行动。这基本上作为一个标志，表示该物品可用于滑翔。这仅在该物品也有 `DataComponents#EQUIPPABLE` 条目时有效。

```java
new Item(
    new Item.Properties()
        .component(DataComponents.GLIDER, Unit.INSTANCE) // 设置为滑翔翼
        .component(DataComponents.EQUIPPABLE, /*...*/) // 确定要检查的槽位以查看是否可以使用
);
```

### 工具，通过工具材料

物品中的 `Tier` 已被 `ToolMaterial` 取代，后者更好地处理工具和剑的创建，而无需手动实现每个方法。`ToolMaterial` 接受与 `Tier` 相同的参数，只是作为单个构造函数的参数，而不是作为可实现的方法。然后，将 `ToolMaterial` 传递给 `DiggerItem` 子类型，以及两个表示攻击伤害和攻击速度的浮点数。内部调用 `ToolMaterial#apply*Properties`，它将 `ToolMaterial` 信息应用到 `DataComponents#TOOL` 以及给定 `float` 中的属性。

```java
// 某个工具材料
public static final ToolMaterial WOOD = new ToolMaterial(
    BlockTags.INCORRECT_FOR_WOODEN_TOOL, // Tier#getIncorrectBlocksForDrops
    59, // Tier#getUses
    2.0F, // Tier#getSpeed
    0.0F, // Tier#getAttackDamageBonus
    15, // Tier#getEnchantmentValue
    ItemTags.WOODEN_TOOL_MATERIALS // Tier#getRepairIngredient
);

// 构造 DiggerItem 子类型时
new PickaxeItem(
    WOOD, // 工具材料
    1.0f, // 攻击伤害
    -2.8f, // 攻击速度
    new Item.Properties()
)
```

## 盔甲材料、装备和模型（纹理）

到目前为止，这是除消耗品之外最大的物品变更。`ArmorMaterial` 实际上已被废弃，因为几乎所有逻辑都在数据组件中处理，并附加到某些资源包 JSON 以加载关联的纹理。乍一看令人烦恼地复杂，但一旦熟悉了流程，就会相当直观。

### `ArmorMaterial`

`ArmorMaterial` 本质上是一个记录，将属性列表转换为它们在数据组件上的适当位置，而不是一个注册表对象。这是通过将物品属性和一个额外的设置传递给 `#humanoidProperties` 或 `#animalProperties` 来完成的。这些设置应该很熟悉，因为它们与以前版本相比没有变化，唯一的区别是它们现在指定了一个“模型 id”，我们将在下面介绍。盔甲材料与 `ArmorType` 一起使用：一个枚举，定义了盔甲放置的装备槽位、每种盔甲类型的单位耐久度以及名称（仅用于构造属性修饰符 id）。

```java
ArmorMaterial exampleArmorMaterial = new ArmorMaterial(
    15, // 与盔甲类型相乘的耐久度标量
    // 一个 ArmorType -> 要应用到实体 ARMOR 属性的半盔甲条数的映射
    // 应该为所有 ArmorType 设置
    Util.make(new EnumMap<>(ArmorType.class), map -> {
        map.put(ArmorType.BOOTS, 2);
        map.put(ArmorType.LEGGINGS, 5);
        map.put(ArmorType.CHESTPLATE, 6);
        map.put(ArmorType.HELMET, 2);
        map.put(ArmorType.BODY, 5);
    }),
    25, // 盔甲的附魔值
    SoundEvents.ARMOR_EQUIP_IRON, // 包装的声音事件持有者，表示装备物品时应发出的声音
    0f, // ARMOR_TOUGHNESS 属性值
    2f, // KNOCKBACK_RESISTANCE 属性值,
    ItemTags.REPAIRS_DIAMOND_ARMOR, // 表示可以修复此盔甲的物品的物品标签
    // EquipmentModel JSON 的相对位置
    // 指向 assets/examplemod/models/equipment/example_armor_material.json
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_armor_material")
)
```

使用 `ArmorMaterial`，可以将其应用于物品属性，通过调用 `humanoidProperties` 将盔甲应用到特定的 `ArmorType`；或者调用 `animalProperties` 将盔甲应用到 `BODY` 并只允许特定实体穿戴它们。

这是否意味着 `ArmorItem` 和 `AnimalArmorItem` 实际上毫无意义？对于 `AnimalArmorItem`，这可以争论。`AnimalArmorItem` 所做的只是有一个 `$BodyType` 参数，这意味着盔甲只能应用于马或狼，并指定物品破碎声音。另一方面，`ArmorItem` 只有一个特定用例：确定物品是否可以脱下或交换。这隐式检查当前穿戴的盔甲物品，看它是否不能脱下（通过 `PREVENT_ARMOR_CHANGE` 附魔），并计算替换盔甲材料上的属性，以便任何热交换只会提高穿戴者的盔甲属性值。

让我们深入一层。

### 数据组件

`ArmorMaterial` 指定了要应用于物品的八个数据组件：

- `MAX_DAMAGE` - 设置为物品的最大耐久度乘以 `ArmorType` 单位耐久度
- `MAX_STACK_SIZE` - 设置为 1
- `DAMAGE` - 设置为 0
- `ATTRIBUTE_MODIFIERS` - 设置 `ARMOR` 和 `ARMOR_TOUGHNESS` 属性，以及当大于 0 时的 `KNOCKBACK_RESISTANCE`
- `ENCHANTABLE` - 设置为附魔值（调用 `animalProperties` 时不设置）
- `REPAIRABLE` - 设置为表示修复原料的标签键的 `HolderSet`
- `EQUIPPABLE` - 设置槽位、装备声音、模型 id、哪些实体可以穿戴该物品，以及是否可从发射器发射

除 `EQUIPPABLE` 之外的所有内容都已在上文解释或从先前版本就已存在，因此本入门文档从现在起只关注 `EQUIPPABLE`。

### Equippable

`Equippable` 曾经是一个接口，现在是一个数据组件，包含实体如何装备此物品以及装备是否应被渲染。因此，一个物品只能装备到一个槽位。这可以通过 `Equippable` 构造函数或通过 `Equippable#builder` 构建器完成。

```java
new Item(
    new Item.Properties()
    .component(DataComponents.EQUIPPABLE, new Equippable(
        EquipmentSlot.HEAD, // 物品可以装备到的槽位
        SoundEvents.ARMOR_EQUIP_IRON, // 装备物品时播放的声音
        // EquipmentModel JSON 的相对位置
        // 指向 assets/examplemod/models/equipment/example_armor_material.json
        // 当设置为空 optional 时，物品不会尝试渲染为装备
        Optional.of(ResourceLocation.fromNamespaceAndPath("examplemod", "example_armor_material")),
        // 穿戴时覆盖在玩家屏幕上的纹理的相对位置
        // 指向 assets/examplemod/textures/example_overlay.png
        // 当设置为空 optional 时，不在玩家屏幕上渲染
        Optional.of(ResourceLocation.withDefaultNamespace("examplemod", "example_overlay")),
        // 可以装备此物品的实体的 HolderSet（直接或标签）
        // 当设置为空 optional 时，任何实体都可以装备此物品
        Optional.of(HolderSet.direct(EntityType::builtInRegistryHolder, EntityType.ZOMBIE)),
        // 物品是否可以从发射器中发射时装备
        true,
        // 在快速装备期间物品是否可以从玩家身上交换下来
        false,
        // 物品在受到攻击时是否应该损坏（通常用于装备）
        // 也必须是可损坏的物品
        false
    ))
);
```

### 装备模型？

如上所述，`Equippable` 物品以及 `ArmorMaterial` 委托可以指定一个模型 id 来确定装备应如何渲染。但是，这个 id 链接到什么？它指向一个序列化为 JSON 的 `EquipmentModel`，位于资源包的 `models/equipment` 中。此 JSON 定义了要渲染的可装备物品的层和纹理。这不指定模型，因此这个记录有些用词不当。最好将其视为应用于传入模型的装备纹理。

`EquipmentModel` 作为先前 `ArmorMaterial$Layer` 的一个更具功能通用性的版本，后者已被移除。每个 `EquipmentModel` 实际上是一个 `$LayerType` 到要渲染的 `$Layer` 列表的映射。

`$LayerType` 是一个枚举，表示要渲染装备模型的层。虽然这些是非特定的，但它们由特定的实体渲染器通过层渲染器实现和读取。例如，`HUMANOID` 由 `HumanoidArmorLayer` 用于渲染头部、胸部和脚部；因此，任何对 `HUMANOID` 的使用都将使用该系统进行渲染。另一个例子是 `WOLF_BODY` 由 `WolfArmorLayer` 用于渲染身体盔甲。因此，如果使用现有的层类型（除非您的模组加载器支持枚举扩展，否则这是唯一的情况），请确保它们与现有的渲染器兼容。

`$Layer` 列表指定了在传入模型上渲染时使用的纹理和可染色选项。第一个参数指定纹理位置，相对于 `textures/entity/equipment`。第二个参数指定一个可选项，表示纹理是否可以被染色（通过 `ItemTags#DYEABLE` 与 `DYED_COLOR` 数据组件一起存储）。当指定时，可以指定一个可选颜色用于物品未染色时。如果为空，则物品未染色时盔甲将不可见。最后一个参数指示是否应改用提供给渲染器的纹理，例如为玩家渲染自定义鞘翅纹理时。

```json5
// 在 assets/examplemod/models/equipment/example_armor_material.json
{
    // 层映射
    "layers": {
        // 要应用的 EquipmentModel$LayerType 的序列化名称
        "humanoid": [
            // 按列表中提供的顺序渲染的层列表
            {
                // 层的相对纹理
                // 指向 assets/examplemod/textures/entity/equipment/example.png
                "texture": "examplemod:example",
                // 当指定时，允许纹理被 DYED_COLOR 数据组件中的颜色染色
                // 否则，不能染色
                "dyeable": {
                    // 一个 RGB 值（总是不透明的颜色）
                    // 0x7683DE 作为十进制
                    // 当未指定时，设置为 0（意味着透明或不可见）
                    "color_when_undyed": 7767006
                },
                // 为 true 时，改用传递给层渲染器的纹理
                "use_player_texture": true
            }
            // ...
        ]
        // ...
    }
}
```

```java
EquipmentModel.builder()
    .addLayers(EquipmentModel.LayerType.HUMANOID, new EquipmentModel.Layer(
        // 层的相对纹理
        // 指向 assets/examplemod/textures/entity/equipment/example.png
        ResourceLocation.fromNamespaceAndPath("examplemod", "example"),
        // 当指定时，允许纹理被 DYED_COLOR 数据组件中的颜色染色
        // 否则，不能染色
        Optional.of(new EquipmentModel.Dyeable(
            // 一个 RGB 值（总是不透明的颜色）
            // 当未指定时，设置为 0（意味着透明或不可见）
            Optional.of(0x7683DE)
        )),
        // 为 true 时，改用传递给层渲染器的纹理
        true
    )/*, ... */)
    .build();
```

然后通过在 `EntityRenderer` 或 `RenderLayer` 的渲染函数中调用 `EquipmentLayerRenderer#renderLayers` 来渲染装备模型。`EquipementLayerRenderer` 作为渲染上下文的一部分通过 `EntityRendererProvider$Context#getEquipmentRenderer` 传入。

```java
// 在某个渲染方法中，其中 EquipmentLayerRenderer equipmentLayerRenderer 是一个字段
this.equipmentLayerRenderer.renderLayers(
    // 要渲染的层类型
    EquipmentModel.LayerType.HUMANOID,
    // 表示 EquipmentModel JSON 的模型 id
    // 这将在 `EQUIPPABLE` 数据组件中通过 `model` 设置
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_armor_material"),
    // 要将纹理应用到的模型
    // 这些通常是与实体模型分开的模型
    // 并且是链接到 LayerDefinition 的单独 ModelLayer
    model,
    // 表示作为模型渲染的物品的物品堆栈
    // 这仅用于获取可染色、闪光和盔甲纹饰信息
    stack,
    // 用于在正确位置渲染模型的堆栈
    poseStack,
    // 用于获取渲染类型顶点消费者的缓冲区源
    bufferSource,
    // 打包的光照纹理
    lighting,
    // 当某个层的 use_player_texture 为 true 时，如果不为 null，则渲染的纹理的绝对路径
    ResourceLocation.fromNamespaceAndPath("examplemod", "textures/other_texture.png");
)
```

### 物品的技术性变更

- `net.minecraft.client.Minecraft#getEquipmentModels` - 获取包含当前装备模型纹理的 `EquipmentModelSet`。
- `net.minecraft.client.gui.GuiGraphics#renderTooltip`、`renderComponentTooltip` 现在有一个参数，用于接受工具提示背景和框架纹理的相对目录，如果为 `null` 则使用默认值
- `net.minecraft.client.gui.screens.inventory.tooltip.TooltipRenderUtil#renderTooltipBackground` 现在有一个参数，用于接受工具提示背景和框架纹理的相对目录，如果为 `null` 则使用默认值
- `net.minecraft.client.renderer.block.model`
    - `ItemOverrides` -> `BakedOverrides`
        - 构造函数不再接受父级 `BlockModel`
        - `resolve` -> `findOverride`，不再接受后备模型
    - `ItemOverride`、`ItemOverride$Predicate` 现在是一个记录
        - `getPredicates` 已移除，使用 `predicates`
        - `getModel` -> `model`
- `net.minecraft.client.renderer.entity`
    - `EntityRenderDispatcher` 现在接受 `EquipmentModelSet`
    - `EntityRendererProvider$Context`
        - `getEquipmentModels` - 获取当前装备纹理。
        - `getEquipmentRenderer` - 获取装备的渲染器。
    - `ItemRenderer` 不再接受 `Minecraft` 实例和 `TextureManager`
        - `TRIDENT_MODEL`、`SPYGLASS_MODEL` 现在是公开的
        - `TRIDENT_IN_HAND_MODEL`、`SPYGLASS_IN_HAND_MODEL` 已移除
        - `getItemModelShaper` 已移除
        - `renderBundleWithSelectedItem` -> `renderBundleItem`，不是一对一
- `net.minecraft.client.renderer.entity.layers`
    - `CapeLayer` 现在接受 `EquipmentModelSet`
    - `ElytraLayer` -> `WingsLayer`
        - 构造函数现在接受 `EquipmentLayerRenderer`
    - `EquipmentLayerRenderer` - 在提供的模型上渲染装备层的渲染器。
    - `HorseArmorLayer` 现在接受 `EquipmentLayerRenderer`
    - `HumanoidArmorLayer` 现在接受 `EquipmentLayerRenderer` 而不是 `ModelManager`
        - `shouldRender` - 返回可装备物品是否应在给定槽位中渲染。
    - `LlamaDecorLayer` 现在接受 `EquipmentLayerRenderer`
    - `WolfArmorLayer` 现在接受 `EquipmentLayerRenderer`
- `net.minecraft.client.renderer.entity.player.PlayerRenderer#getArmPose` 现在是私有的，被一个只接受 `HumanoidArm` 和 `PlayerRenderState` 的公共方法取代
- `net.minecraft.client.resources.model`
    - `EquipmentModelSet` - 从 `models/equipment` 加载 `EquipmentModel` 的资源监听器。
    - `ItemModel` - 物品的模型。
- `net.minecraft.core.component.DataComponents`
    - `ITEM_MODEL` - 返回物品的模型。`item/` 被剥离，意味着 `minecraft:apple` 指向 `minecraft/textures/models/item/apple.json`。
    - `EQUIPPABLE` - 表示物品在给定槽位中是可装备的。还包含要渲染的装备模型。
    - `GLIDER` - 表示物品可用于在空中滑翔。必须与 `EQUIPPABLE` 一起使用。
    - `TOOLTIP_STYLE` - 确定表示工具提示应如何渲染的相对位置
- `net.minecraft.core.dispenser.EquipmentDispenseItemBehavior` - 处理如何从发射器中发射装备。
- `net.minecraft.core.registries.BuiltInRegistries#`、`Registries#ARMOR_MATERIAL` 不再是一个注册表，完全通过数据组件处理
- `net.minecraft.world.entity`
    - `EquipmentSlot#getFilterFlag` -> `getId`
        - 还有一个方法 `getFilterBit` 用于将 ID 转换为位掩码
    - `LivingEntity`
        - `canContinueToGlide` -> `canGlide`，不再接受 `ItemStack`
        - `canTakeItem` 被 `DataComponents#EQUIPPABLE` 取代
        - `canEquipWithDispenser` - 返回堆栈在从发射器发射时是否可以装备。
        - `canDispenserEquipIntoSlot` - 一个实体覆盖，指定发射器是否可以将装备放入给定槽位。
        - `isEquippableInSlot` - 返回堆栈是否可以在给定槽位中装备。
        - `canGlideUsing` - 实体是否可以使用提供的槽位中的堆栈滑翔。
    - `Mob`
        - `canReplaceCurrentItem` 现在接受 `EquipmentSlot`
        - `isBodyArmorItem` 被 `DataComponents#EQUIPPABLE` 取代
- `net.minecraft.world.entity.animal.horse`
    - `Horse#isBodyArmorItem` 被 `DataComponents#EQUIPPABLE` 取代
    - `Llama#isBodyArmorItem`、`getSwag` 被 `DataComponents#EQUIPPABLE` 取代
- `net.minecraft.world.item`
    - `AnimalArmorItem` 不再继承 `ArmorItem`
        - 构造函数不再接受一个表示覆盖纹理的布尔值，因为现在这是 `EquipmentModel` 的一部分
        - 构造函数可以接受一个可选的 `Holder<SoundEvent>` 作为装备声音
        - 构造函数可以接受一个 `boolean` 表示如果实体受伤，盔甲是否应该损坏
        - `$BodyType` 现在接受允许穿戴盔甲的实体，而不是指向纹理的路径工厂
    - `ArmorItem` 不再是可装备的
        - 基本上作为一个物品类，其剩余的唯一用途是在附魔时防止盔甲更换并获取关联的属性
        - `$Type` -> `ArmorType`
    - `ArmorMaterial` -> `.equipment.ArmorMaterial`
        - 基本上是一个虚拟记录，用于轻松处理应用关联的数据组件（`MAX_DAMAGE`、`ATTRIBUTE_MODIFIERS`、`ENCHANTABLE`、`EQUIPPABLE`、`REPAIRABLE`）
    - `ArmorMaterials` -> `.equipment.ArmorMaterials`
    - `BookItem`、`EnchantedBookItem` -> `DataComponents#WRITTEN_BOOK_CONTENT`
    - `BundleItem` 现在接受一个 `ResourceLocation` 作为模型，而不是仅仅字符串
        - `$Mutable#setSelectedItem` -> `toggleSelectedItem`
    - `ComplexItem` 类已移除
    - `ElytraItem` 类已移除，现在只是带有 `DataComponents#GLIDER` 的物品
    - `Equippable` -> `.equipment.Equippable`，现在是一个定义物品如何装备的记录
    - `FoodOnAStackItem` 参数顺序已交换
    - `InstrumentItem` 参数顺序已交换
    - `Item`
        - `descriptionId` 现在是 protected
        - `getDescription` -> `getName`
        - `getOrCreateDescriptionId` 已移除
        - `getDescriptionId(ItemStack)` -> `DataComponents#ITEM_NAME`
        - `isEnchantable`、`getEnchantmentValue` 已移除
        - `isValidRepairItem` 已移除
        - `getDefaultAttributeModifiers` 已移除
        - `getDamageSource` - 返回此物品对 `LivingEntity` 造成的伤害来源
        - `isComplex` 已移除
        - `$Properties`
            - `equippable` - 设置一个可装备组件，定义物品如何装备
            - `equippableUnswappable` - 设置一个无法通过按键快捷方式交换的可装备组件。
            - `overrideDescription` - 设置物品的翻译键。
            - `overrideModel` - 设置模型资源位置。
        - `getCraftingRemainingItem`、`hasCraftingRemainingItem` -> `getCraftingRemainder`
    - `ItemNameBlockItem` 类已移除，只是一个带有 `useItemDescriptionPrefix` 属性的普通 `Item`
    - `ItemStack`
        - `ITEM_NON_AIR_CODEC` -> `Item#CODEC`
        - `isValidRepairItem` - 返回堆栈是否可以由此堆栈修复。
        - `nextDamageWillBreak` - 检查下一次受到的伤害是否会破坏物品。
        - `getDescriptionId` -> `getItemName`，不是一对一，因为现在它返回完整的组件
    - `ShieldItem` 不再实现 `Equippable`，通过 `DataComponents#EQUIPPABLE` 传入
    - `SignItem` 参数顺序已交换
    - `SmithingTemplateItem` 参数顺序已交换，移除了 `FeatureFlag`
    - `StandingAndWallBlockItem` 参数顺序已交换
    - `AxeItem` 现在接受两个表示攻击伤害和攻击速度的浮点数
    - `DiggerItem` 现在接受两个表示攻击伤害和攻击速度的浮点数
        - `createAttributes` -> `ToolMaterial#applyToolProperties`
    - `HoeItem` 现在接受两个表示攻击伤害和攻击速度的浮点数
    - `PickaxeItem` 现在接受两个表示攻击伤害和攻击速度的浮点数
    - `ShovelItem` 现在接受两个表示攻击伤害和攻击速度的浮点数
    - `SwordItem` 现在接受两个表示攻击伤害和攻击速度的浮点数
        - `createAttributes` -> `ToolMaterial#applySwordProperties`
    - `Tier` -> `ToolMaterial`
    - `TieredItem` 类已移除
    - `Tiers` 常量存储在 `ToolMaterial` 上
- `net.minecraft.world.item.alchemy.Potion` 名称现在是必需的
        - `getName` -> `name`，不是一对一，因为这直接存储在药水上，没有任何其他处理
- `net.minecraft.world.item.armortrim.*` -> `.equipment.trim.*`
- `net.minecraft.world.item.component`
    - `Tool` 中返回 `Tool$Rule` 的方法现在只接受 `HolderSet` 的方块，而不是列表或标签键
    - `DamageResistant` - 一个组件，包含物品作为实体或穿戴时对其免疫的伤害类型标签
- `net.minecraft.world.item.enchantment`
    - `Enchantable` - 物品附魔值的数据组件对象。
    - `Repairable` - 可以修复此物品的物品的数据组件对象。
- `net.minecraft.world.level.block`
    - `AbstractSkullBlock` 不再实现 `Equippable`
    - `EquipableCarvedPumpkinBlock` 类已移除，被 `DataComponents#EQUIPPABLE` 取代
    - `WoolCarpetBlock` 不再实现 `Equippable`

## 交互结果

`InteractionResult` 已被完全修改，将所有内容包含在一系列密封的实现中。新的 `InteractionResult` 实现结合了 `InteractionResultHolder` 和 `ItemInteractionResult`，因此所有用途也已被替换。

`InteractionResult` 现在是一个接口，根据结果类型有四个实现。首先是 `$Pass`，表示交互检查应传递给调用堆栈中的下一个对象。`$Fail`，当用于物品和方块时，阻止调用堆栈中的任何进一步执行。对于实体，这将被忽略。最后，`$TryEmptyHandInteraction` 告诉调用堆栈尝试用空手应用点击，专门用于物品-方块交互。

还有 `$Success`，表示交互成功并且可以被消费。成功指定了两条信息：`$SwingSource`，表示挥动来源（`CLIENT` 或 `SERVER`）或 `NONE`（如果未指定），以及 `$ItemContext`，处理手中物品是否有交互，以及物品被转换成了什么。

这些对象都不应直接初始化。这些实现通过 `InteractionResult` 接口上的六个常量处理：

- `SUCCESS` - 一个在客户端挥动手的 `$Success` 对象。
- `SUCCESS_SERVER` - 一个在服务器端挥动手的 `$Success` 对象。
- `CONSUME` - 一个不挥动手的 `$Success` 对象。
- `FAIL` - 一个 `$Fail` 对象。
- `PASS` - 一个 `$Pass` 对象。
- `TRY_WITH_EMPTY_HAND` - 一个 `$TryEmptyHandInteraction` 对象。

```java
// 对于某个返回 InteractionResult 的方法
return InteractionResult.PASS;
```

对于成功对象，如果物品交互应转换持有的堆栈，则调用 `$Success#heldItemTransformedTo`，或者如果没有物品用于交互，则调用 `$Success#withoutItem`。

```java
// 对于某个返回 InteractionResult 的方法
return InteractionResult.SUCCESS.heldItemTransformedTo(new ItemStack(Items.APPLE));

// 或者
return InteractionResult.SUCCESS.withoutItem();
```

- `net.minecraft.core.cauldron.CauldronInteraction`
    - `interact` 现在返回一个 `InteractionResult`
    - `fillBucket`、`emptyBucket` 现在返回一个 `InteractionResult`
- `net.minecraft.world`
    - `InteractionResultHolder`、`ItemInteractionResult` -> `InteractionResult`
- `net.minecraft.world.item`
    - `Equipable#swapWithEquipmentSlot` 现在返回一个 `InteractionResult`
    - `Item#use`、`ItemStack#use` 现在返回一个 `InteractionResult`
    - `ItemUtils#startUsingInstantly` 现在返回一个 `InteractionResult`
    - `JukeboxPlayable#tryInsertIntoJukebox` 现在返回一个 `InteractionResult`
- `net.minecraft.world.level.block.state.BlockBehaviour#useItemOn`、`$BlockStateBase#useItemOn` 现在返回一个 `InteractionResult`

## 乐器 数据包版

`Instrument`（不是 `NoteBlockInstrument`）现在是一个数据包注册表，意味着它们必须在 JSON 中定义或通过数据生成生成。

```json5
// 在 data/examplemod/instrument/example_instrument.json
{
    // 声音事件的注册表名称
    "sound_event": "minecraft:entity.arrow.hit",
    // 使用乐器的秒数
    "use_duration": 7.0,
    // 方块范围，每个方块为 16 个单位
    "range": 256.0,
    // 乐器的描述
    "description": {
        "translate": "instrument.examplemod.example_instrument"
    },
}
```

```java
// 对于某个 RegistrySetBuilder builder
builder.add(Registries.INSTRUMENT, bootstrap -> {
    bootstrap.register(
        ResourceKey.create(Registries.INSTRUMENT, ResourceLocation.fromNamespaceAndPath("examplemod", "example_instrument")),
        new Instrument(
            BuiltInRegistries.SOUND_EVENT.wrapAsHolder(SoundEvents.ARROW_HIT),
            7f,
            256f,
            Component.translatable(Util.makeDescriptionId("instrument", ResourceLocation.fromNamespaceAndPath("examplemod", "example_instrument")))
        )
    )
});
```

- `net.minecraft.world.item`
    - `Instrument` 接受一个 `float` 作为使用持续时间和一个 `Component` 描述。
    - `InstrumentItem#setRandom` 已移除

## 试炼刷怪笼配置，现在采用数据包形式

`TrialSpawnConfig` 现在是一个数据包注册表，意味着它们必须在 JSON 中定义或通过数据生成生成。

```json5
// 在 data/examplemod/trial_spawner/example_config.json
{
    // 实体可以从试炼刷怪笼方块生成的区域范围
    "spawn_range": 2,
    // 可以生成的生物总数
    "total_mobs": 10.0,
    // 一次可以生成的生物数量
    "simultaneous_mobs": 4.0,
    // 试炼中每个玩家增加的生物数量
    "total_mobs_added_per_player": 3.0,
    // 试炼中每个玩家增加的一次可以生成的生物数量
    "simultaneous_mobs_added_per_player": 2.0,
    // 每次生成之间的刻数
    "ticks_between_spawn": 100,
    // 生成时选择的实体的加权列表
    "spawn_potentials": [
        {
            // SpawnData
            "data": {
                // 要生成的实体
                "entity": {
                    "id": "minecraft:zombie"
                }
            },
            // 权重值
            "weight": 1
        }
    ],
    // 给予奖励时选择的战利品表的权重列表
    "loot_tables_to_eject": [
        {
            // 战利品键
            "data": "minecraft:spawners/ominous/trial_chamber/key",
            // 权重值
            "weight": 1
        }
    ],
    // 试炼刷怪笼为不祥时使用的战利品表
    "items_to_drop_when_ominous": "minecraft:shearing/bogged"
}
```

```java
// 对于某个 RegistrySetBuilder builder
builder.add(Registries.TRIAL_SPAWNER_CONFIG, bootstrap -> {
    var entityTag = new CompoundTag();
    entityTag.putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.ZOMBIE).toString());

    bootstrap.register(
        ResourceKey.create(Registries.INSTRUMENT, ResourceLocation.fromNamespaceAndPath("examplemod", "example_config")),
        TrialSpawnerConfig.builder()
            .spawnRange(2)
            .totalMobs(10.0)
            .simultaneousMobs(4.0)
            .totalMobsAddedPerPlayer(3.0)
            .simultaneousMobsAddedPerPlayer(2.0)
            .ticksBetweenSpawn(100)
            .spawnPotentialsDefinition(
                SimpleWeightedRandomList.single(new SpawnData(entityTag, Optional.empty(), Optional.empty()))
            )
            .lootTablesToEject(
                SimpleWeightedRandomList.single(BuiltInLootTables.SPAWNER_OMINOUS_TRIAL_CHAMBER_KEY)
            )
            .itemsToDropWhenOminous(
                BuiltInLootTables.BOGGED_SHEAR
            )
            .build()
    )
});
```

- `net.minecraft.world.level.block.entity.trialspawner`
    - `TrialSpawner` 现在接受 `TrialSpawnerConfig` 的 `Holder`
        - `canSpawnInLevel` 现在接受一个 `ServerLevel`
    - `TrialSpawnerConfig`
        - `CODEC` -> `DIRECT_CODEC`
        - `$Builder`、`builder` - 试炼刷怪笼配置的构建器

## 配方提供者，数据提供者的“并非真正”

`RecipeProvider` 不再是 `DataProvider`。相反，通过实现 `createRecipeProvider`，使用 `RecipeProvider$Runner` 构造 `RecipeProvider`。还必须指定提供者的名称。

```java
public class MyRecipeProvider extends RecipeProvider {

    // 参数存储在 protected 字段中
    public MyRecipeProvider(HolderLookup.Provider registries, RecipeOutput output) {
        super(registries, output);
    }

    @Override
    protected void buildRecipes() {
        // 在此处注册配方
    }

    // runner 类，这应该作为 DataProvider 添加到 DataGenerator 中
    public static class Runner extends RecipeProvider.Runner {

        public Runner(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
            super(output, registries)
        }

        @Override
        protected RecipeProvider createRecipeProvider(HolderLookup.Provider registries, RecipeOutput output) {
            return new VanillaRecipeProvider(registries, output);
        }

        @Override
        public String getName() {
            return "My Recipes";
        }
    }
}
```

- `net.minecraft.data.recipes`
    - `RecipeOutput#includeRootAdvancement` - 生成配方的根进度。
    - `RecipeProvider` 不再继承 `DataProvider`
        - 构造函数接受查找提供者和一个 `RecipeOutput`，它们是 protected 字段
        - `buildRecipes` 不接受任何参数
        - 所有生成方法都不接受 `RecipeOutput` 并且是实例方法
        - `$FamilyRecipeProvider` - 通过传入结果方块和基础方块的 `Block` 为 `BlockFamily` 创建配方。
        - `$Runner` - 一个 `DataProvider`，通过 `createRecipeProvider` 构造 `RecipeProvider`
    - `ShapedRecipeBuilder`、`ShapelessRecipeBuilder` 现在有私有构造函数，并接受物品的 holder getter

## 原料的转变

`Ingredient` 已被重新实现，使用 `HolderSet` 作为其基础，而不是其自己的内部 `Ingredient$Value`。这主要改变了 `Ingredient#of` 的调用，因为您需要为其提供 `Item` 对象或代表标签的 `HolderSet`。有关如何执行此操作的更多信息，请参阅[持有者集部分](#持有者集-过渡)。

- `net.minecraft.world.item.crafting.Ingredient`
    - `EMPTY` -> `Ingredient#of`，但默认用例不允许空原料
    - `CODEC` 已移除
    - `CODEC_NONEMPTY` -> `CODEC`
    - `testOptionalIngredient` - 如果存在，则测试堆栈是否在原料内，否则默认为空检查。
    - `getItems` -> `items`
    - `getStackingIds` 已移除
    - `of(ItemStack...)`、`of(Stream<ItemStack>)` 已移除
    - `of(TagKey)` -> `of(HolderSet)`，需要解析标签键

## BlockEntityTypes 私有化了！

`BlockEntityType` 已被完全私有化，构建器也被移除！这意味着，如果模组加载器或模组没有提供对构造函数的某种访问扩宽，您将无法创建新的方块实体。唯一的其他变更是，数据修复器的 `Type` 已被移除，意味着只需要提供客户端构造函数和方块实体可以位于的有效方块集合。

```java
// 如果 BlockEntityType 构造函数被设为公共
// MyBlockEntity(BlockPos, BlockState) 构造函数
BlockEntityType<MyBlockEntity> type = new BlockEntityType(MyBlockEntity::new, MyBlocks.EXAMPLE_BLOCK);
```

## 消耗品

使用物品已被进一步扩展，大部分已过渡到单独的数据组件条目。

### `Consumable` 数据组件

`Consumable` 数据组件定义了物品在使用完成时如何使用。这实际上起到了以前 `FoodProperties` 的作用，除了所有消耗逻辑都集中在这个组件中。一个消耗品有五个属性：消耗或使用物品所需的秒数、消耗时播放的动画、消耗时播放的声音、消耗期间是否应出现粒子，以及[消耗完成后要应用的效果](#consumeeffect)。

可以使用 `food` 物品属性应用 `Consumable`。如果只应添加 `Consumable`，则应调用 `component`。原版消耗品和构建器的列表可以在 `Consumables` 中找到。

```java
// 对于某个物品
Item exampleItem = new Item(new Item.Properties().component(DataComponents.CONSUMABLE,
    Consumable.builder()
    .consumeSeconds(1.6f) // 将在 1.6 秒或 32 刻内使用该物品
    .animation(ItemUseAnimation.EAT) // 使用时要播放的动画
    .sound(SoundEvents.GENERIC_EAT) // 使用消耗品时要播放的声音
    .soundAfterConsume(SoundEvents.GENERIC_DRINK) // 消耗后播放的声音（委托给 'onConsume'）
    .hasConsumeParticles(true) // 设置是否显示粒子
    .onConsume(
        // 完成消耗后，以 30% 的概率应用效果
        new ApplyStatusEffectsConsumeEffect(new MobEffectInstance(MobEffects.HUNGER, 600, 0), 0.3F)
    )
    // 可以有多个
    .onConsume(
        // 在 50 格半径内随机传送实体
        new TeleportRandomlyConsumeEffect(100f)
    )
    .build()
));
```

#### `OnOverrideSound`

有时，实体在消耗物品时可能想要播放不同的声音。在这种情况下，实体可以实现 `Consumable$OverrideConsumeSound` 并返回应播放的声音事件。

```java
// 在您自己的实体上
public class MyEntity extends Mob implements Consumable.OverrideCustomSound {
    // ...

    @Override
    public SoundEvent getConsumeSound(ItemStack stack) {
        // 返回要播放的声音事件
    }
}
```

### `ConsumableListener`

`ConsumableListener` 是表示在堆栈被“消耗”后要应用的动作的数据组件。这意味着自从玩家开始使用消耗品以来，`Consumable#consumeTicks` 过去之后。这方面的一个例子是 `FoodProperties`。`ConsumableListener` 只有一个方法 `#onConsume`，它接受消耗发生的等级、实体、进行消耗的堆栈以及已完成消耗的 `Consumable`。

```java
// 在您自己的数据组件上
public record MyDataComponent() implements ConsumableListener {

    // ...

    @Override
    public void onConsume(Level level, LivingEntity entity, ItemStack stack, Consumable consumable) {
        // 物品被消耗后执行操作。
    }
}
```

### `ConsumeEffect`

现在有一个数据组件处理物品被实体消耗时发生的事情，恰当地称为 `ConsumeEffect`。当前的效果范围从添加/移除状态效果、随机传送玩家，或仅仅播放声音。这些效果通过将效果传递给 `Consumable` 或构建器中的 `onConsume` 来应用。

```java
// 构造消耗品时
Consumable exampleConsumable = Consumable.builder()
    .onConsume(
        // 完成消耗后，以 30% 的概率应用效果
        new ApplyStatusEffectsConsumeEffect(new MobEffectInstance(MobEffects.HUNGER, 600, 0), 0.3F)
    )
    // 可以有多个
    .onConsume(
        // 在 50 格半径内随机传送实体
        // 注意：当前有 bug，只允许 8 格半径
        new TeleportRandomlyConsumeEffect(100f)
    )
    .build();
```

### 使用转换

消耗时将物品转换为另一个堆栈现在通过 `DataComponents#USE_REMAINDER` 处理。只有当使用后堆栈为空时，剩余物才会被转换。否则，它将返回当前堆栈，只是使用了一个物品。

```java
// 对于某个物品
Item exampleItem = new Item(new Item.Properties().usingConvertsTo(
    Items.APPLE // 消耗时将此物品转换为苹果
)); 
Item exampleItem2 = new Item(new Item.Properties().component(DataComponents.USE_REMAINDER,
    new UseCooldown(
        new ItemStack(Items.APPLE, 3) // 消耗时转换为三个苹果
    )
));
```

### 冷却时间

物品冷却时间现在通过 `DataComponents#USE_COOLDOWN` 处理；然而，它们已被扩展，可以根据其定义的组对堆栈应用冷却时间。一个冷却组要么引用 `Item` 注册表名称（如果未指定），要么引用一个自定义资源位置。应用冷却时间时，它将冷却实例存储在匹配定义组的任何东西上。这意味着，如果某个堆栈定义了冷却组，当使用普通物品时，它不会受到影响。

```java
// 对于某个物品
Item exampleItem = new Item(new Item.Properties().useCooldown(
    60 // 等待 60 秒
    // 将对 'my_mod:example_item' 组中的物品应用冷却时间（假设这是注册表名称）
)); 
Item exampleItem2 = new Item(new Item.Properties().component(DataComponents.USE_COOLDOWN,
    new UseCooldown(
        60, // 等待 60 秒
        // 将对 'my_mod:custom_group' 组中的物品应用冷却时间
        Optional.of(ResourceLocation.fromNamespaceAndPath("my_mod", "custom_group"))
    )
));
```

- `net.minecraft.core.component.DataComponents#FOOD` -> `CONSUMABLE`
- `net.minecraft.world.entity.LivingEntity`
    - `getDrinkingSound`、`getEatingSound` 已移除，由 `ConsumeEffect` 处理
    - `triggerItemUseEffects` 已移除
    - `eat` 已移除
- `net.minecraft.world.entity.npc.WanderingTrader` 现在实现 `Consumable$OverrideConsumeSound`
- `net.minecraft.world.food`
    - `net.minecraft.world.food.FoodData`
        - `tick` 现在接受一个 `ServerPlayer`
        - `getLastFoodLevel`、`getExhaustionLevel`、`setExhaustion` 已移除
    - `FoodProperties` 现在是一个 `ConsumableListener`
        - `eatDurationTicks`、`eatSeconds` -> `Consumable#consumeSeconds`
        - `usingConvertsTo` -> `DataComponents#USE_REMAINDER`，
        - `effects` -> `ConsumeEffect`
- `net.minecraft.world.item`
    - `ChorusFruitItem` 类已移除
    - `HoneyBottleItem` 类已移除
    - `Item`
        - `getDrinkingSound`、`#getEatingSound` 已移除，由 `ConsumeEffect` 处理
        - `releaseUsing` 现在返回一个 `boolean` 表示是否成功释放
        - `$Properties#food` 现在可以接受一个 `Consumable` 用于自定义逻辑
        - `$Properties#usingConvertsTo` - 使用后要转换成的物品。
        - `$Properties#useCooldown` - 再次使用物品前等待的秒数。
    - `ItemCooldowns` 现在接受 `ItemStack` 或 `ResourceLocation` 作为其方法的参数，而不仅仅是 `Item`
        - `getCooldownGroup` - 返回表示应用冷却时间的组的键
    - `ItemStack#getDrinkingSound`、`getEatingSound` 已移除
    - `MilkBucketItem` 类已移除
    - `OminousBottleItem` 类已移除
    - `SuspiciousStewItem` 类已移除
- `net.minecraft.world.item.alchemy.PotionContents` 现在实现 `ConsumableListener`
    - 构造函数接受一个可选的字符串，表示自定义名称的翻译键后缀
    - `applyToLivingEntity` - 将所有效果应用到提供的实体。
    - `getName` - 通过将自定义名称附加到提供的内容字符串末尾来获取名称组件。
- `net.minecraft.world.item.component`
    - `Consumable` - 一个定义何时可以消耗物品的数据组件。
    - `ConsumableListener` - 应用于可被消耗的数据组件的接口，在消耗完成后执行。
    - `SuspiciousStewEffects` 现在实现 `ConsumableListener`
    - `UseCooldown` - 一个定义如何应用堆栈冷却时间的数据组件。
    - `UseRemainder` - 一个定义物品用完后应如何替换的数据组件。
    - `DeathProtection` - 一个包含 `ConsumeEffect` 列表的数据组件，用于定义使用物品以在死亡中幸存时要执行的操作。
- `net.minecraft.world.item.consume_effects.ConsumeEffect` - 物品完成消耗后要应用的效果。

## 注册表对象 ID，在属性里？

当向 `Block` 提供 `BlockBehaviour$Properties` 或向 `Item` 提供 `Item$Properties` 时，必须通过调用 `#setId` 直接在方块中设置 `ResourceKey`。如果在传入之前未设置此值，将抛出错误。

```java
new Block(BlockBehaviour.Properties.of()
    .setId(ResourceKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath("examplemod", "example_block"))));

new BlockItem(exampleBlock, new Item.Properties()
    .useBlockDescriptionPrefix() // 为方块物品制作描述 id
    .setId(ResourceKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath("examplemod", "example_item"))));

new Item(new Item.Properties()
    .setId(ResourceKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath("examplemod", "example_item"))));
```

- `net.minecraft.world.item.Item$Properties`
    - `setId` - 设置物品的资源键，以获取默认描述和模型。此属性必须设置。
    - `useBlockDescriptionPrefix` - 使用 `block.` 前缀创建描述 id。
    - `useItemDescriptionPrefix` - 使用 `item.` 前缀创建描述 id。
- `net.minecraft.world.level.block.state.BlockBehaviour$Properties#setId` - 设置方块的资源键，以获取默认掉落和描述。此属性必须设置。

## 属性变更

`DirectionProperty` 已被移除，现在必须通过 `EnumProperty#create` 调用并带有 `Direction` 泛型来引用。此外，所有属性类都已成为 final，并且必须通过公开的 `create` 方法之一来构造。

- `net.minecraft.world.level.block.state.properties`
    - `BooleanProperty` 现在是 final
    - `DirectionProperty` 类已移除
    - `EnumProperty` 现在是 final
        - `create` 现在接受一个 `List` 而不是 `Collection`
    - `IntegerProperty` 现在是 final
    - `Property#getPossibleValues` 现在返回一个 `List` 而不是 `Collection`

## 配方，现在采用注册表格式

配方已升级为数据包注册表，类似于战利品表的处理方式。它们仍然以相同的方式查询，只是简单地使用一个伪注册表支持的实例。一些更常见的变化是，`RecipeHolder` 可能被 `RecipeDisplayId`、`RecipeDisplay` 或 `RecipeDisplayEntry` 取代，如果不需要 holder 本身的话。随之而来的是，配方书的处理方式也有一些变化。

### 配方书

`RecipeBookComponent` 已被修改，以容纳一个要渲染的菜单的泛型实例。因此，该组件不再实现 `PlacedRecipe`，而是接受一个代表 `RecipeBookMenu` 的泛型。菜单通过其构造函数传递给组件，而不是通过 `init` 方法。这也意味着 `RecipeBookMenu` 没有任何关联的泛型。要创建一个组件，需要扩展该类。

```java
// 假设某个 MyRecipeMenu 继承 AbstractContainerMenu
public class MyRecipeBookComponent extends RecipeBookComponent<MyRecipeMenu> {

    public MyRecipeBookComponent(MyRecipeMenu menu, List<RecipeBookComponent.TabInfo> tabInfos) {
        super(menu, tabInfos);
        // ...
    }

    @Override
    protected void initFilterButtonTextures() {
        // ...
    }

    @Override
    protected boolean isCraftingSlot(Slot slot) {
        // ...
    }

    @Override
    protected void selectMatchingRecipes(RecipeCollection collection, StackedItemContents contents) {
        // ...
    }

    @Override
    protected Component getRecipeFilterName() {
        // ...
    }

    @Override
    protected void fillGhostRecipe(GhostSlots slots, RecipeDisplay display, ContextMap ctx) {

    }
}

public class MyContainerScreen extends AbstractContainerScreen<MyRecipeMenu> implements RecipeUpdateListener {

    public MyContainerScreen(MyRecipeMenu menu, List<RecipeBookComponent.TabInfo> tabInfos, ...) {
        super(menu, ...);
        this.recipeBookComponent = new MyRecipeBookComponent(menu, tabInfos);
    }
    

    // 完整实现请参见 AbstractFurnaceScreen
}
```

### 配方显示

但是，配方如何理解应在配方书中显示什么？这属于两个新的静态注册表：`RecipeDisplay` 和 `SlotDisplay`。

`SlotDisplay` 表示配方中单个槽位内显示的内容。该显示只有一个方法（忽略类型）：`resolve`。`resolve` 接受包含数据的 `ContextMap` 和 `DisplayContentsFactory`，后者接受将在该槽位中显示的堆栈和剩余物。`SlotDisplay` 还有许多辅助实现，例如 `$Composite` 接受一个显示列表，或 `$ItemStackSlotDisplay` 接受要显示的堆栈。该显示通过其 `$Type` 注册，该类型接受映射编解码器和流编解码器。

槽位还有通过 `resolveForStacks` 和 `resolveForFirstStack` 获取可显示的相关堆栈的方法。

```java
public static record MySlotDisplay() implements SlotDisplay {

    @Override
    public <T> Stream<T> resolve(ContextMap ctx, DisplayContentsFactory<T> output) {
        // 调用 output.forStack(...) 或 addRemainder(..., ...) 使用 instanceof 来显示物品
        if (output instanceof ForStacks<T> stacks) {
            stacks.forStack(...);
        } else if (output instanceof ForRemainders<T> remainders) {
            remainders.addRemainder(..., ...);
        }
    }

    @Override
    public SlotDisplay.Type<? extends SlotDisplay> type() {
        // 返回在此处注册到 Registries#SLOT_DISPLAY 的注册对象
    }
}
```

`RecipeDisplay` 表示如何显示一个配方。作为实现细节，`RecipeDisplay` 只需要知道结果（通过 `result` 槽位显示）和配方使用的位置（通过 `craftingStation` 槽位显示），因为这是配方书关心的唯一两个细节。但是，也建议为原料设置槽位显示，然后由您的 `RecipeBookComponent` 消耗它们。该显示通过其 `$Type` 注册，该类型接受映射编解码器和流编解码器。

```java
public record MyRecipeDisplay(SlotDisplay result, SlotDisplay craftingStation, ...) implements RecipeDisplay {

    @Override
    public RecipeDisplay.Type<? extends RecipeDisplay> type() {
        // 返回在此处注册到 Registries#RECIPE_DISPLAY 的注册对象
    }
}
```

### 配方放置

配方书中的配方原料和放置现在通过 `Recipe#placementInfo` 处理。`PlacementInfo` 基本上是一个定义配方包含的物品以及它们在菜单中应放置的位置（如果支持）的定义。如果配方无法放置，例如如果它不是 `Item` 或使用堆栈信息，则应返回 `PlacementInfo#NOT_PLACEABLE`。

`PlacementInfo` 可以通过 `Ingredient`、`List<Ingredient>` 或 `List<Optional<Ingredient>>` 使用 `create` 或 `createFromOptionals` 分别创建。

```java
public class MyRecipe implements Recipe<RecipeInput> {

    private PlacementInfo info;

    public MyRecipe(Ingredient input) {
        // ...
    }

    // ...

    @Override
    public PlacementInfo placementInfo() {
        // 这种委托是因为支持原料的 HolderSet 可能在构造函数中没有完全填充
        if (this.info == null) {
            this.info = PlacementInfo.create(input);
        }

        return this.info;
    }
}
```

如果使用 `Optional<Ingredient>`，可以通过 `Ingredient#testOptionalIngredient` 进行测试。

- `net.minecraft.world.item.crafting`
    - `Ingredient#display` - 返回显示此原料的 `SlotDisplay`。
    - `PlacementInfo` - 定义构造配方结果所需的所有原料。
    - `Recipe`
        - `getToastSymbol` -> `getCategoryIconItem`
        - `getIngredients`、`isIncomplete` -> `placementInfo`
            - `getIngredients` -> `PlacementInfo#stackedRecipeContents`，
            - `isIncomplete` -> `PlacementInfo#isImpossibleToPlace`
    - `RecipeManager#getSynchronizedRecipes` - 返回所有可以放置的配方并将它们发送到客户端。没有其他配方被同步。
    - `ShapedRecipePattern` 现在接受一个 `List<Optional<Ingredient>>` 而不是 `NonNullList<Ingredient>`
    - `ShapelessRecipe` 现在接受一个 `List<Ingredient>` 而不是 `NonNullList<Ingredient>`
    - `SmithingTransformRecipe`、`SmithingTrimRecipe` 现在接受 `Optional<Ingredient>` 而不是 `Ingredient`
    - `SuspiciousStewRecipe` 类已移除

### 配方变更

配方类本身有一些变化，它们反映了上述所有变化。首先，`canCraftInDimensions` 已移除，现在硬编码到匹配函数中。`getResultItem` 和 `getCategoryIconItem` 已被 `RecipeDisplay` 通过 `display` 取代。`getRemainingItems` 已移至 `CraftingRecipe`。最后，所有配方现在通过 `recipeBookCategory` 返回它们的 `RecipeBookCategory`。

```java
public class MyRecipe implements Recipe<RecipeInput> {

    @Override
    public String group() {
        // 在此处返回之前 `getGroup` 的内容
    }

    @Override
    public List<RecipeDisplay> display() {
        return List.of(
            // 某个 RecipeDisplay 实例
            // RecipeDisplay#result 应返回 `getResultItem`
            // RecipeDisplay#craftingStation 应返回 `getCategoryIconItem`
        )
    }

    @Override
    public RecipeBookCategory recipeBookCategory() {
        // 功能类似于数据生成期间传递给配方构建器的书类别
        return RecipeBookCategories.CRAFTING_MISC;
    }
}
```

### 创建配方书类别

配方书类别通过 `ExtendedRecipeBookCategory` 统一，并分为两个部分：`RecipeBookCategory` 用于实际类别，以及 `SearchRecipeBookCategory` 用于聚合类别。`SearchRecipeBookCategory` 是枚举，而 `RecipeBookCategory` 像任何其他静态注册表对象一样。这是通过创建一个新的 `RecipeBookCategory` 来完成的。

```java
// 使用标准的原版注册表方法
public static final RecipeBookCategory EXAMPLE_CATEGORY = Registry.register(
    BuiltInRegistries.RECIPE_BOOK_CATEGORY,
    // 注册表对象名称
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_category"),
    // 这将创建一个新的配方书类别。它作为一个标记对象。
    new RecipeBookCategory()
);
```

### 技术性变更

- `net.minecraft.advancements.AdvancementRewards` 现在接受一个 `ResourceKey` 列表而不是 `ResourceLocation` 作为配方
    - `$Builder#recipe`、`addRecipe` 现在接受一个 `ResourceKey`
- `net.minecraft.advancements.critereon`
    - `PlayerPredicate` 现在接受一个 `ResourceKey` 作为配方映射
        - `$Builder#addRecipe` 现在接受一个 `ResourceKey`
    - `RecipeCraftedTrigger`
        - `trigger` 现在接受一个 `ResourceKey`
        - `$TriggerInstance` 现在接受一个 `ResourceKey`
        - `$TriggerInstance#craftedItem`、`crafterCraftedItem` 现在接受一个 `ResourceKey`
    - `RecipeUnlockedTrigger`
        - `unlocked` 现在接受一个 `ResourceKey`
        - `$TriggerInstance` 现在接受一个 `ResourceKey`
- `net.minecraft.client`
    - `ClientRecipeBook`
        - `setupCollections` -> `rebuildCollections`，不是一对一
        - `getCollection(RecipeBookCategories)` -> `getCollection(ExtendedRecipeBookCategory)`
        - `add`、`remove` - 处理在配方书中添加/移除要显示的配方条目。
        - `addHighLight`、`removeHighlight`、`hasHighlight` - 处理当被玩家过滤或选择时条目是否高亮显示。
        - `clear` - 清除已知和高亮显示的配方。
    - `RecipeBookCategories#*_MISC` -> `SearchRecipeBookCategory#*`
        - 这也可以在方法中被 `RecipeBookComponent$TabInfo`、`ExtendedRecipeBookCategory` 或 `RecipeBookCategory` 取代
- `net.minecraft.client.gui.components.toasts`
    - `RecipeToast(RecipeHolder)` -> `RecipeToast()`，现在是私有的
    - `addOrUpdate` 现在接受一个 `RecipeDisplay` 而不是 `RecipeHolder`
- `net.minecraft.client.gui.screens.inventory.AbstractFurnaceScreen`
    - `recipeBookComponent` 现在是私有的
    - `AbstractFurnaceScreen(T, AbstractFurnaceRecipeBookComponent, Inventory, Component, ResourceLocation, ResourceLocation, ResourceLocation)` - `AbstractFurnaceRecipeBookComponent` 已被 `Component` 取代，因为配方书不是在内部构造的，并且现在接受一个 `RecipeBookComponent$TabInfo` 列表
- `net.minecraft.client.gui.screens.recipebook`
    - `AbstractFurnaceReipceBookComponent`、`BlastingFurnaceReipceBookComponent`、`SmeltingFurnaceReipceBookComponent`、`SmokingFurnaceReipceBookComponent` -> `FurnaceReipceBookComponent`
    - `GhostRecipe` -> `GhostSlots`，不是一对一，因为配方本身作为 `RecipeHolder` 存储在 `RecipeBookComponent` 的一个私有字段中
        - `addResult` -> `setResult`，不是一对一
        - `addIngredient` -> `setIngredient`，不是一对一
        - `setSlot`、`setInput`、`setResult` 现在接受一个 `ContextMap`
    - `OverlayRecipeComponent()` -> `OverlayRecipeComponent(SlotSelectTime, boolean)`
        - `init` 接受一个包含注册表数据的 `ContextMap` 以在组件中显示，以及一个 `boolean` 表示配方书是否正在过滤，而不是从 `Minecraft` 实例计算
        - `getLastRecipeClicked` 现在返回一个 `RecipeDisplayId`
        - `$OverlayRecipeButton` 现在是一个抽象的包私有类，接受 `ContextMap`
        - `$Pos` 现在是一个记录
    - `RecipeBookComponent` 不再实现 `RecipeShownListener`
        - 构造函数接受一个 `$TabInfo` 列表，其中包含书中显示的标签页
        - `init` 不再接受一个 `RecipeBookMenu`
        - `initVisuals` 现在是私有的
        - `initFilterButtonTextures` 现在是抽象的
        - `updateCollections` 现在接受另一个布尔值，表示书是否正在过滤
        - `renderTooltip` 现在接受一个可为 null 的 `Slot` 而不是一个表示槽位索引的 `int`
        - `renderGhostRecipe` 不再接受一个表示延迟时间的 `float`
        - `setupGhostRecipe` -> `fillGhostRecipe`，不再接受要放置的 `List<Slot>`，这存储在组件本身中
        - `selectMatchingRecipes` 不再接受 `RecipeBook`
        - `recipesShown` 现在接受一个 `RecipeDisplayId`
        - `setupGhostRecipeSlots` -> `fillGhostRecipe`，接受 `ContextMap`
        - `$TabInfo` - 一个记录，表示配方书页面中要显示的图标和配方类别。
    - `RecipeBookPage()` -> `RecipeBookPage(RecipeBookComponent, SlotSelectTime, boolean)`
        - `updateCollections` 现在接受一个布尔值，表示书是否正在过滤
        - `getMinecraft` 已移除
        - `addListener` 已移除
        - `getLastRecipeClicked` 现在返回一个 `RecipeDisplayId`
        - `recipesShown` 现在接受一个 `RecipeDisplayId`
        - `getRecipeBook` 现在返回一个 `ClientRecipeBook`
    - `RecipeBookTabButton` 现在接受一个 `RecipeBookComponent$TabInfo`
        - `startAnimation(Minecraft)` -> `startAnimation(ClientRecipeBook, boolean)`
        - `getCategory` 现在返回一个 `ExtendedRecipeBookCategory`
    - `RecipeButton()` -> `RecipeButton(SlotSelectTime)`
        - `init` 现在接受一个 `boolean` 表示书是否正在过滤，以及一个 `ContextMap` 保存注册表数据
        - `getRecipe` -> `getCurrentRecipe`，不是一对一
        - `getDisplayStack` - 返回配方的结果堆栈。
        - `getTooltipText` 现在接受 `ItemStack`
    - `RecipeCollection(RegistryAccess, List<RecipeHolder>)` -> `RecipeCollection(List<RecipeDisplayEntry>)`
        - `canCraft` -> `selectRecipes`
        - `getRecipes`、`getDisplayRecipes` -> `getSelectedRecipes`
        - `registryAccess`、`hasKnownRecipes`、`updateKnownRecipes` 已移除
        - `isCraftable` 现在接受一个 `RecipeDisplayId`
        - `hasFitting` -> `hasAnySelected`
        - `getRecipes` 现在返回一个 `RecipeDisplayEntry` 列表
    - `RecipeShownListener` 类已移除
    - `RecipeUpdateListener`
        - `getRecipeBookComponent` 已移除
        - `fillGhostRecipe` -> 给定 `RecipeDisplay` 填充幽灵配方
    - `SearchRecipeBookCategory` - 一个枚举，包含聚合类型的配方书类别。
    - `SlotSelectTime` - 表示玩家选择的当前槽位索引。
- `net.minecraft.client.multiplayer`
    - `ClientPacketListener#getRecipeManager` -> `recipes`，返回 `RecipeAccess`
    - `ClientRecipeContainer` - 当从服务器同步时，`RecipeAccess` 的客户端实现。
    - `MultiPlayerGameMode#handlePlaceRecipe` 现在接受一个 `RecipeDisplayId`
    - `SessionSearchTrees#updateRecipes` 现在接受一个 `Level` 而不是 `RegistryAccess$Frozen`
- `net.minecraft.client.player.LocalPlayer#removeRecipeHightlight` 现在接受一个 `RecipeDisplayId`
- `net.minecraft.commands.SharedSuggestionProvider#getRecipeNames` 已移除，因为它可以从注册表访问中查询
- `net.minecraft.commands.arguments.ResourceLocationArgument`
    - `getRecipe` -> `ResourceKeyArgument#getRecipe`
    - `getAdvancement` -> `ResourceKeyArgument#getAdvancement`
- `net.minecraft.commands.synchronization.SuggestionProviders#ALL_RECIPES` 已移除
- `net.minecraft.core.component.DataComponents#RECIPES` 现在接受一个 `ResourceKey` 列表
- `net.minecraft.data.recipes`
    - `RecipeBuilder#save` 现在接受一个 `ResourceKey` 而不是 `ResourceLocation`
    - `RecipeOutput#accept` 现在接受一个 `ResourceKey` 而不是 `ResourceLocation`
    - `RecipeProvider#trimSmithing` 现在接受一个 `ResourceKey` 而不是 `ResourceLocation`
- `net.minecraft.network.protocol.game`
    - `ClientboundPlaceGhostRecipePacket` - 一个包含容器 id 和 `RecipeDisplay` 的数据包
    - `ClientboundRecipeBookAddPacket` - 向配方书添加条目的数据包
    - `ClientboundRecipeBookRemovePacket` - 从配方书移除条目的数据包
    - `ClientboundRecipeBookSettingsPacket` - 指定配方书设置的数据包
    - `ClientboundRecipePacket` 类已移除
    - `ClientboundUpdateRecipesPacket` 现在是一个记录，接受配方的属性集和切石机配方
        - `getRecipes` 已移除
    - `ServerboundPlaceRecipePacket` 现在是一个记录
    - `ServerboundRecipeBookSeenRecipePacket` 现在是一个记录
- `net.minecraft.recipebook`
    - `PlaceRecipe` -> `PlaceRecipeHelper`
        - `addItemToSlot` -> `$Output#addItemToSlot`
        - `placeRecipe` 现在接受一个 `Recipe` 而不是 `RecipeHolder`
            - 有一个重载接受两个额外的 int，表示 `ShapedRecipe` 的模式高度和宽度，或者只是重复前两个 int
    - `RecipeBook`
        - `add`、`contains`、`remove` -> `ServerRecipeBook#add`、`contains`、`remove`
        - `addHighlight`、`removeHighlight`、`willHighlight` -> `ServerRecipeBook#addHighlight`、`removeHighlight`、`ClientRecipeBook#hasHighlight`
        - `bookSettings` 现在是 protected
    - `RecipeBookSettings#read`、`write` 现在是私有的
    - `ServerPlaceRecipe` 不再直接可访问，而是通过 `#placeRecipe` 作为 `RecipeBookMenu$PostPlaceAction` 访问和返回
        - `$CraftingMenuAccess` - 定义如何与可放置配方菜单进行交互。
    - `ServerRecipeBook`
        - `fromNbt` 现在接受一个 `ResourceKey` 的谓词而不是 `RecipeManager`
        - `copyOverData` - 从另一个配方书读取数据。
        - `$DisplayResolver` - 通过传入 `RecipeDisplayEntry` 来解析要显示的配方
- `net.minecraft.stats.RecipeBook#isFiltering(RecipeBookMenu)` 已移除
- `net.minecraft.world.entity.player`
    - `Player#awardRecipesByKey` 现在接受一个 `ResourceKey` 列表
    - `StackedItemContents#canCraft` 接受原料信息列表的重载
- `net.minecraft.world.inventory`
    - `AbstractCraftingMenu` - 一个用于合成界面的菜单。
    - `AbstractFurnaceMenu` 现在接受 `RecipePropertySet` 键
    - `CraftingMenu#slotChangedCraftingGrid` 现在接受一个 `ServerLevel` 而不是 `Level`
    - `ItemCombinerMenu` 现在接受一个 `ItemCombinerMenuSlotDefinition`
        - `mayPickup` 现在默认为 `true`
    - `ItemCombinerMenuSlotDefinition#hasSlot`、`getInputSlotIndexes` 已移除
    - `RecipeBookMenu` 不再接受任何泛型
        - `handlePlacement` 现在是抽象的，并返回一个 `$PostPlaceAction`，接受一个额外的 `ServerLevel`
            - 这将移除所有基本的配方放置调用，因为这将在内部由 `ServerPlaceRecipe` 处理
    - `RecipeCraftingHolder#setRecipeUser` 不再接受一个 `Level`
    - `SmithingMenu#hasRecipeError` - 返回当物品放置在库存中时配方是否有错误。
- `net.minecraft.world.item.crafting`
    - `AbstractCookingRecipe` 现在实现 `SingleItemRecipe`
        - 构造函数不再接受 `RecipeType`，因此用户需要覆盖 `getType` 方法
        - `getExperience` -> `experience`
        - `getCookingTime` -> `cookingTime`
        - `furnaceIcon` - 返回炉子的图标。
        - `$Serializer` - 烹饪配方序列化器实例的便利实现。
    - `CookingBookCategory` 现在有一个整数 id
    - `CraftingRecipe#defaultCrafingRemainder` - 获取合成配方中应保留的堆栈。
    - `CustomRecipe$Serializer` - 自定义配方序列化器实例的便利实现。
    - `ExtendedRecipeBookCategory` - 表示配方书内类别的统一接口。
    - `Ingredient#optionalIngredientToDisplay` - 将可选原料转换为 `SlotDisplay`。
    - `Recipe#getRemainingItems` -> `CraftingRecipe#getRemainingItems`
    - `RecipeAccess` - 一个访问器，返回包含可用配方输入的属性集。
    - `RecipeBookCategory` - 表示配方书内单个类别的对象。
    - `RecipeCache#get` 现在接受一个 `ServerLevel` 而不是 `Level`
    - `RecipeHolder` 现在接受一个 `ResourceKey`
    - `RecipeManager` 现在继承 `SimplePreparableReloadLsitener<RecipeMap>` 并实现 `RecipeAccess`
        - `prepare` - 从配方注册表创建配方映射
        - `logImpossibleRecipes`、`hasErrorsLoading` 已移除
        - `getRecipeFor` 现在接受一个 `ResourceKey`，之前是 `ResourceLocation`
        - `getRecipesFor`、`getAllRecipesFor` -> `RecipeMap#getRecipesFor`
        - `byType` 已移除
        - `getRemainingItemsFor` 已移除
        - `byKey`、`byKeyTyped` 现在接受一个 `ResourceKey`
        - `getOrderedRecipes` 已移除
        - `getSynchronizedRecipes` -> `getSynchronizedItemProperties`、`getSynchronizedStonecutterRecipes`；不是一对一
        - `getRecipeIds` 已移除
        - `getRecipeFromDisplay` - 根据其 id 获取配方显示信息。
        - `listDisplaysForRecipe` - 接受要显示的配方的显示条目列表。
        - `replaceRecipes` 已移除
        - `$CachedCheck#getRecipeFor` 现在接受一个 `ServerLevel` 而不是 `Level`
        - `$IngredientCollector` - 一个从配方中提取原料并将其添加到 `RecipePropertySet` 的配方消费者
        - `$IngredientExtractor` - 一个在存在时获取配方的原料的方法。
        - `$ServerDisplayInfo` - 一个将显示条目链接到其配方持有者的记录。
    - `RecipeMap` - 一个通过配方类型和资源键映射配方持有者的类。
    - `RecipePropertySet` - 一组可用作给定配方槽位输入的原料。用于只允许特定输入到屏幕上的槽位。
    - `SelectableRecipe` - 一个包含槽位显示及其关联配方的记录。目前仅用于切石机菜单。
    - `SimpleCookingSerializer` -> `AbstractCookingRecipe$Serializer`
    - `SingleItemRecipe` 不再接受 `RecipeType` 或 `RecipeSerializer`
        - `ingredient`、`result`、`group` 现在是私有的
        - `input`、`result` - 配方的槽位。
- `net.minecraft.world.item.crafting.display`
    - `DisplayContentsFactory` - 用于接受配方内容的一个工厂。其子类型接受配方的堆栈和剩余物。
    - `RecipeDisplay` - 用于显示配方内容的显示处理器。
    - `RecipeDisplayEntry` - 一个将配方显示链接到其标识符、类别和合成需求的记录。
    - `RecipeDisplayId` - 配方显示的标识符。
    - `SlotDisplay` - 用于显示配方内槽位内容的显示处理器。
    - `SlotDisplayContext` - 槽位显示使用的上下文键。
- `net.minecraft.world.level.Level#getRecipeManager` -> `recipeAccess`，在 `Level` 上返回 `RecipeAccess`，但在 `ServerLevel` 上返回 `RecipeManager`
- `net.minecraft.world.level.block.CrafterBlock#getPotentialResults` 现在接受一个 `ServerLevel` 而不是 `Level`
- `net.minecraft.world.level.block.entity.CampfireBlockEntity`
    - `getCookableRecipe` 已移除
    - `placeFood` 现在接受一个 `ServerLevel` 而不是 `Level`

## 小幅迁移

以下是有用或有趣的增加、变更和移除的列表，它们不值得在入门文档中拥有自己的章节。

### 语言文件的移除与重命名

`assets/minecraft/lang` 中翻译键的所有移除和重命名现在显示在 `deprecated.json` 中。

### 条件，通过 HolderGetter 提供

在构造期间，所有条件构建器现在都接受一个 `HolderGetter`。虽然这可能不会被使用，但这是用来代替直接调用静态注册表来获取关联的 `Holder` 和 `HolderSet`。

- `net.minecraft.advancement.critereon`
    - `BlockPredicate$Builder#of`
    - `ConsumeItemTrigger$TriggerInstance#usedItem`
    - `EntityEquipmentPredicate#captainPredicate`
    - `EntityPredicate$Builder#of`
    - `EntityTypePredicate#of`
    - `ItemPredicate$Builder#of`
    - `PlayerTrigger$TriggerInstance#walkOnBlockWithEquipment`
    - `ShotCrossbowTrigger$TriggerInstance#shotCrossbow`
    - `UsedTotemTrigger$TriggerInstance#usedToItem`

### MacosUtil#IS_MACOS

`com.mojang.blaze3d.platform.MacosUtil#IS_MACOS` 已被添加，以替换在渲染过程中指定布尔值。

- `com.mojang.blaze3d.pipeline`
    - `RenderTarget#clear(boolean)` -> `clear()`
    - `TextureTarget(int, int, boolean, boolean)` -> `TextureTarget(int, int, boolean)`
- `com.mojang.blaze3d.platform.GlStateManager#_clear(boolean)` -> `_clear()`
- `com.mojang.blaze3d.systems.RenderSystem#clear(int, boolean)` -> `clear(int)`

### 雾参数

单个值的雾方法已被 `FogParameters` 数据对象取代。

- `com.mojang.blaze3d.systems.RenderSystem`
    - `setShaderFogStart`、`setShaderFogEnd`、`setShaderFogColor`、`setShaderFogShape` -> `setShaderFog`
    - `getShaderFogStart`、`getShaderFogEnd`、`getShaderFogColor`、`getShaderFogShape` -> `getShaderFog`
- `net.minecraft.client.renderer.FogRenderer`
    - `setupColor` -> `computeFogColor`，返回一个 `Vector4f`
    - `setupNoFog` -> `FogParameters#NO_FOG`
    - `setupFog` 现在接受一个 `Vector4f` 作为颜色，并返回 `FogParameters`
    - `levelFogColor` 已移除

### 新标签

- `minecraft:banner_pattern`
    - `bordure_indented`
    - `field_masoned`
- `minecraft:block`
    - `bats_spawnable_on`
    - `pale_oak_logs`
- `minecraft:damage_type`
    - `mace_smash`
- `minecraft:item`
    - `diamond_tool_materials`
    - `furnace_minecart_fuel`
    - `gold_tool_materials`
    - `iron_tool_materials`
    - `netherite_tool_materials`
    - `villager_picks_up`
    - `wooden_tool_materials`
    - `piglin_safe_armor`
    - `repairs_leather_armor`
    - `repairs_chain_armor`
    - `repairs_iron_armor`
    - `repairs_gold_armor`
    - `repairs_diamond_armor`
    - `repairs_netherite_armor`
    - `repairs_turtle_helmet`
    - `repairs_wolf_armor`
    - `duplicates_allays`
    - `brewing_fuel`
    - `panda_eats_from_ground`
    - `shulker_boxes`
    - `bundles`
    - `map_invisibility_equipment`
    - `pale_oak_logs`
    - `gaze_disguise_equipment`
- `minecraft:entity_type`
    - `boat`

### 更智能的帧率限制

不再仅仅在玩家不在等级中或在屏幕或覆盖层中时限制帧率，而是根据不同的动作有不同的行为。这是通过 `FramerateLimitTracker` 使用 `InactivityFpsLimit` 完成的。这增加了两个额外的检查。如果窗口最小化，游戏以 10 fps 运行。如果用户一分钟没有输入，那么游戏以 30 fps 运行。十分钟没有输入后为 10 fps。

- `com.mojang.blaze3d.platform.FramerateLimitTracker` - 一个根据设定值限制帧率的跟踪器。
- `com.mojang.blaze3d.platform#Window#setFramerateLimit`、`getFramerateLimit` 已移除
- `net.minecraft.client`
    - `InactivityFpsLimit` - 一个枚举，定义了当窗口最小化或玩家离开键盘时如何限制 FPS。
    - `Minecraft#getFramerateLimitTracker` - 返回帧率限制器。

### 燃料值

`FuelValues` 已取代 `AbstractFurnaceBlockEntity` 中的静态映射。它的功能与该映射相同，只是燃料值存储在 `MinecraftServer` 本身上，并可提供给单个 `Level` 实例。可以通过访问 `MinecraftServer` 或 `Level` 并调用 `fuelValues` 方法来获取映射。

- `net.minecraft.client.multiplayer.ClientPacketListener#fuelValues` - 返回燃料的燃烧时间。
- `net.minecraft.server.MinecraftServer#fuelValues` - 返回燃料的燃烧时间。
- `net.minecraft.server.level.Level#fuelValues` - 返回燃料的燃烧时间。
- `net.minecraft.world.level.block.entity`
    - `AbstractFurnaceBlockEntity`
        - `invalidateCache`、`getFuel` -> `Level#fuelValues`
        - `getBurnDuration` 现在接受 `FuelValues`
        - `isFuel` -> `FuelValues#isFuel`
    - `FuelValues` - 一个包含燃料物品列表及其关联燃烧时间的类

### 发光强度

发光强度数据现在被烘焙到四边形中，可以使用 `light_emission` 标签添加到面中。

- `net.minecraft.client.renderer.block.model`
    - `BakedQuad` 现在接受一个 `int` 表示发光强度
        - `getLightEmission` - 返回四边形的发光强度。
    - `BlockElement` 现在接受一个 `int` 表示发光强度
    - `FaceBakery#bakeQuad` 现在接受一个 `int` 表示发光强度

### 地图纹理

地图纹理现在通过 `MapTextureManager`（处理动态纹理）和 `MapRenderer`（处理地图渲染）来处理。地图装饰仍然通过 `map_decorations` 精灵文件夹加载。

- `net.minecraft.client`
    - `Minecraft`
        - `getMapRenderer` - 获取地图的渲染器。
        - `getMapTextureManager` - 获取地图的纹理管理器。
- `net.minecraft.client.resources#MapTextureManager` - 处理为地图创建动态纹理。
- `net.minecraft.client.gui.MapRenderer` -> `net.minecraft.client.renderer.MapRenderer`
- `net.minecraft.client.renderer#GameRenderer#getMapRenderer` -> `Minecraft#getMapRenderer`

### 朝向

随着红石线实验的加入，邻居变化带来了一个新类：`Orientation`。`Orientation` 实际上是两个方向和一个侧面偏置的组合。`Orientation` 用作一种方式，根据上下文的连接方向和偏置来传播更新。目前，这对不使用新红石线系统的人来说没有任何意义，因为所有对邻居方法的其他调用都将其设置为 `null`。然而，它确实提供了一种简单的方法来逐步传播行为。

- `net.minecraft.client.renderer.debug.RedstoneWireOrientationsRenderer` - 红石线朝向的调试渲染器。
- `net.minecraft.world.level.Level`
    - `updateNeighborsAt` - 使用指定的 `Orientation` 更新给定位置的邻居。
    - `updateNeighborsAtExceptFromFacing`、`neighborChanged` 现在接受一个 `Orientation`
- `net.minecraft.world.level.block.RedStoneWireBlock`
    - `getBlockSignal` - 返回方块信号的强度。
- `net.minecraft.world.level.block.state.BlockBehaviour`
    - `neighborChanged`、`$BlockStateBase#handleNeighborChanged` 现在接受一个 `Orientation` 而不是邻居 `BlockPos`
    - `updateShape` 现在接受 `LevelReader`、`ScheduledTickAccess` 和 `RandomSource` 而不是 `LevelAccessor`；`Direction` 和 `BlockState` 参数的顺序已重新排列
    - `$BlockStateBase#updateShape` 现在接受 `LevelReader`、`ScheduledTickAccess` 和 `RandomSource` 而不是 `LevelAccessor`；`Direction` 和 `BlockState` 参数的顺序已重新排列
- `net.minecraft.world.level.redstone`
    - `CollectingNeighborUpdater$ShapeUpdate#state` -> `neighborState`
    - `NeighborUpdater`
        - `neighborChanged`、`updateNeighborsAtExceptFromFacing`、`executeUpdate` 现在接受一个 `Orientation` 而不是邻居 `BlockPos`
        - `executeShapeUpdate` 交换了 `BlockState` 和邻居 `BlockPos` 的顺序
    - `Orientation` - 方块上连接 `Direction` 的一组，并偏向正面或上面。
    - `RedstoneWireEvaluator` - 传入和传出信号的强度评估器。

### 矿车行为

矿车现在有一个 `MinecartBehavior` 类，处理实体应如何移动和渲染。

- `net.minecraft.core.dispenser.MinecartDispenseItemBehavior` - 定义矿车在从发射器发射时应如何表现。
- `net.minecraft.world.entity.vehicle`
    - `AbstractMinecart`
        - `getMinecartBehavior` - 返回矿车的行为。
        - `exits` 现在是公开的
        - `isFirstTick` - 返回这是否是实体存活的第一个刻。
        - `getCurrentBlockPosOrRailBelow` - 获取矿车的当前位置或下方的铁轨。
        - `moveAlongTrack` -> `makeStepAlongTrack`
        - `setOnRails` - 设置矿车是否在铁轨上。
        - `isFlipped`、`setFlipped` - 返回矿车是否倒置。
        - `getRedstoneDirection` - 返回红石供电的方向。
        - `isRedstoneConductor` 现在是公开的
        - `applyNaturalSlowdown` 现在返回要减速的向量。
        - `getPosOffs` -> `MinecartBehavior#getPos`
        - `setInitialPos` - 设置矿车的初始位置。
        - `createMinecart` 在其创建中现在是抽象的，意味着它可以用于根据提供的参数创建任何矿车
        - `getMinecartType` 已移除
        - `getPickResult` 现在是抽象的
        - `$Type` 和 `getMinecartType` 被 `isRideable` 和 `isFurnace` 取代，不是一对一。
    - `AbstractMinecartContainer(EntityType, double, double, double, Level)` 已移除
    - `MinecartBehavior` - 包含实体在移动过程中应如何渲染和定位。
    - `MinecartFurnace#xPush`、`zPush` -> `push`
- `net.minecraft.world.level.block.state.properties.RailShape#isAscending` -> `isSlope`
- `net.minecraft.world.phys.shapes.MinecartCollisionContext` - 处理矿车与其他碰撞对象碰撞的实体碰撞上下文。

### 爆——炸——！

`Explosion` 现在是一个定义爆炸元数据的接口。它不包含任何实际爆炸自身的方法。然而，`ServerExplosion` 仍然在内部用于处理等级爆炸等。

- `net.minecraft.world.level`
    - `Explosion` -> `ServerExplosion`
    - `Explosion` - 一个定义爆炸应如何发生的接口。
        - `getDefaultDamageSource` - 返回爆炸实例的默认伤害来源。
        - `shouldAffectBlocklikeEntities` - 返回方块实体是否应受到爆炸影响。
        - `level` - 获取 `ServerLevel`
    - `ExplosionDamageCalculator#getEntityDamageAmount` 现在接受一个额外的 `float` 表示所见百分比
    - `Level#explode` 不再返回任何内容
- `net.minecraft.world.level.block.Block#wasExploded` 现在接受一个 `ServerLevel` 而不是 `Level`
- `net.minecraft.world.level.block.state.BlockBehaviour#onExplosionHit`、`$BlockStateBase#onExplosionHit` 现在接受一个 `ServerLevel` 而不是 `Level`

### 移除雕刻生成步骤

`GenerationStep$Carving` 已被移除，意味着所有 `ConfiguredWorldCarver` 都作为单个 `HolderSet` 提供。

```json
// 在某个 BiomeGenerationSettings JSON 中
{
    "carvers": [
        // 在此处放置雕刻器
    ]
}
```

- `net.minecraft.world.level.biome.BiomeGenerationSettings`
    - `getCarvers` 不再接受 `GenerationStep$Carving`
    - `$Builder#addCarver` 不再接受 `GenerationStep$Carving`
    - `$PlainBuilder#addCarver` 不再接受 `GenerationStep$Carving`
- `net.minecraft.world.level.chunk`
    - `ChunkGenerator#applyCarvers` 不再接受 `GenerationStep$Carving`
    - `ProtoChunk#getCarvingMask`、`getOrCreateCarvingMask`、`setCarvingMask` 不再接受 `GenerationStep$Carving`
- `net.minecraft.world.level.levelgen.placement`
    - `CarvingMaskPlacement` 类已移除
    - `PlacementContext#getCarvingMask` 不再接受 `GenerationStep$Carving`

### 可编解码的 JSON 重载监听器

`SimpleJsonResourceReloadListener` 已被重写，使用编解码器而不是纯 `Gson`。

```java
public class MyJsonListener extends SimpleJsonResourceReloadListener<MyJsonObject> {

    // 如果不需要注册表访问，可以移除 HolderLookup$Provider 参数
    public MyJsonListener(HolderLookup.Provider registries, Codec<T> codec, String directory) {
        super(registries, codec, directory);
    }
}
```

- `net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener` 现在接受一个代表 JSON 数据对象的泛型
    - 构造函数现在是 protected，接受数据对象的编解码器、目录的字符串，以及一个可选的 `HolderLookup$Provider` 以在必要时构造 `RegistryOps` 序列化上下文
    - `prepare` 现在返回一个名称到对象的映射
    - `scanDirectory` 现在接受 `DynamicOps` 和 `Codec`

### 连续执行器

`ProcessorMailbox` 和 `ProcessorHandle` 已被分别替换为 `AbstractConsecutiveExecutor` 和 `TaskScheduler`。它们在使用上基本相同，只是可能方法名称不同。

- `net.minecraft.util.thread`
    - `ProcessorMailbox` -> `AbstractConsecutiveExecutor`，不是一对一
        - `ConsecutiveExecutor` 将是等效的实现
    - `PriorityConsecutiveExecutor` - 一个指定调度时任务优先级的执行器。
    - `BlockableEventLoop#wrapRunnable` -> `AbstractConsecutiveExecutor#wrapRunnable`
    - `ProcessorHandle` -> `TaskScheduler`，其中泛型是 `Runnable` 的子类型
        - `tell` -> `schedule`
        - `ask`、`askEither` -> `scheduleWithResult`，不是一对一
        - `of` -> `wrapExecutor`
    - `StrictQueue` 不再接受 `F` 泛型，并使 `T` 成为 `Runnable` 的子类型
        - `pop` 现在返回一个 `Runnable`
        - `$IntRunnable` -> `$RunnableWithPriority`

### 生物转化

通过 `#convertTo` 转化的生物，其逻辑由 `ConversionType`、`ConversionParams` 处理。`ConversionType` 是一个枚举，指示通过 `#convert` 将信息从一个生物复制到另一个生物时要应用的逻辑。常见属性通过 `#convertCommon` 处理，该方法在 `#convert` 方法内部调用。目前有两种类型：`SINGLE`，其中实体一对一地转换为另一个实体；以及 `SPLIT_ON_DEATH`，其中 `Mob#convertTo` 方法被多次调用，例如当史莱姆死亡时。`ConversionParams` 包含关于转化过程的元数据：类型、实体是否可以保留其装备或拾取战利品，以及实体所在的队伍。`Mob#convertTo` 还接受一个生物消费者，用于对实体本身应用任何最终化设置。

```java
// 对于某个 Mob exampleMob
exampleMob.convertTo(
    EntityType.SHEEP, // 要转化成的实体
    new ConversionParams(
        ConversionType.SINGLE, // 一对一
        true, // 保留装备
        false // 不保留拾取战利品
    ),
    EntitySpawnReason.CONVERSION, // 实体生成原因
    sheep -> {
        // 对新建的转化实体执行任何其他设置
    },
)
```

- `net.minecraft.world.entity`
    - `ConversionParams` - 一个包含当生物转化为另一个实体时发生什么的设置的记录
    - `ConversionType` - 一个枚举，定义一个生物如何转化为另一个生物。目前要么是 `SINGLE` 用于一对一，要么是 `SPLIT_ON_DEATH` 用于一对多（仅用于史莱姆）
    - `Mob#convertTo` 现在接受 `ConversionParams`、一个可选的实体 `EntitySpawnReason`（默认为 `CONVERSION`），以及一个用于在转化后设置任何其他信息的生物消费者

### 末影珍珠加载区块

末影珍珠现在通过向区块源添加一个加载票并将实体存储在玩家上来加载它们穿过的区块。

- `net.minecraft.server.level.ServerPlayer`
    - `registerEnderPearl`、`deregisterEnderPearl`、`getEnderPearls` - 处理玩家投掷的末影珍珠。
    - `registerAndUpdateEnderPearlTicket`、`placeEnderPearlTicket` - 处理投掷的末影珍珠的区域加载票。

### 分析器与 Tracy 客户端

分析器已与 Minecraft 实例分离，现在通过 `Profiler#get` 获得。可以通过 `Profiler#use` 上的 try-resource 块添加一个新的分析器实例。此外，分析器添加了一个名为 Tracy 的新库，用于跟踪当前堆栈帧以及捕获屏幕上的图像，如果传入了关联的 `--tracy` 参数。这些部分可以拆分为“区域”，以更细粒度地区分正在发生的事情。

```java
Profiler.get().push("section");
// 在此处执行代码
Profiler.get().pop();
```

- `com.mojang.blaze3d.systems.RenderSystem#flipFrame` 现在接受一个 `TracyFrameCapture`，或 `null`
- `net.minecraft.client.Minecraft#getProfiler` -> `Profiler#get`
- `net.minecraft.client.main.GameConfig$GameData` 现在接受一个布尔值，表示是否通过 tracy 客户端捕获屏幕。
- `net.minecraft.client.multiplayer.ClientLevel` 不再接受 `ProfilerFiller`
- `net.minecraft.server.MinecraftServer#getProfiler` -> `Profiler#get`
- `net.minecraft.server.packs.resources.PreparableReloadListener#reload` 不再接受 `ProfilerFiller`
- `net.minecraft.util.profiling`
    - `Profiler` - 一个用于管理当前活动 `ProfilerFiller` 的静态处理器。
    - `ProfilerFiller`
        - `addZoneText` - 添加文本以在分析当前帧时标记。
        - `addZoneValue` - 在分析当前帧时添加区域的值。
        - `setZoneColor` - 在分析当前帧时设置区域的颜色。
        - `zone` - 添加一个分析器部分，同时创建一个新区域来调用上述方法。
        - `tee` -> `combine`
        - `$CombinedProfileFiller` - 一个写入多个分析器的分析器。
    - `TracyZoneFiller` - 由 tracy 客户端使用的分析器，用于跟踪当前正在分析的区域。
    - `Zone` - 当前正在被 Tracy 分析和解释的部分。
- `net.minecraft.world.entity.ai.goal.GoalSelector` 不再接受提供的 `ProfilerFiller`
- `net.minecraft.world.level`
    - `Level` 不再接受 `ProfilerFiller`
        - `getProfiler`、`getProfilerSupplier` -> `Profiler#get`
    - `PathNavigationRegion#getProfiler` -> `Profiler#get`
- `net.minecraft.world.ticks.LevelTicks` 不再接受 `ProfilerFiller`

### Tick节流器

为了防止玩家垃圾邮件某些动作，添加了 `TickThrottler`。节流器接受阈值和要添加到计数的增量。如果计数小于阈值，则可以发生该动作。计数每刻减少。

- `net.minecraft.util.TickThrottler` - 一个用于限制某些动作发生频率的工具。

### 上下文键

战利品上下文参数已被上下文键取代，这只是对之前类的一个更通用的命名方案。这也导致上下文键用于可能有任意数据的其他上下文中。

简要描述，上下文键系统实际上是一个通用的类型化字典，其中每个 `ContextKey` 保存值类型，然后存储在 `ContextMap` 中的后备映射中。为了强制执行必需和可选参数，`ContextMap` 使用 `ContextKeySet` 构建，它定义了字典映射的键。

- `net.minecraft.advancements.critereon.CriterionValidator#validate` 现在接受一个 `ContextKeySet` 而不是 `LootContextParamSet`
- `net.minecraft.data.loot.LootTableProvider$SubProviderEntry#paramSet` 现在接受一个 `ContextKeySet` 而不是 `LootContextParamSet`
- `net.minecraft.util.context`
    - `ContextKey` - 一个表示对象的键。可以把它看作一个指定值类型的字典键。
    - `ContextKeySet` - 一个键集，指示后备字典必须具有哪些键，以及可以指定的可选键。
    - `ContextMap` - 上下文键到其类型化对象的映射。
- `net.minecraft.world.item.enchantment`
    - `ConditionalEffect#codec` 现在接受一个 `ContextKeySet` 而不是 `LootContextParamSet`
    - `TargetedConditionalEffect#codec` 现在接受一个 `ContextKeySet` 而不是 `LootContextParamSet`
- `net.minecraft.world.level.storage.loot`
    - `LootContext`
        - `hasParam` -> `hasParameter`
        - `getParam` -> `getParameter`
        - `getParamOrNull` - `getOptionalParameter`
        - `$EntityTraget#getParam` 现在返回一个 `ContextKey` 而不是 `LootContextParam`
    - `LootContextUser#getReferencedContextParams` 现在接受一组 `ContextKey` 而不是一组 `LootContextParam`
    - `LootParams` 现在接受一个 `ContextMap` 而不是参数到对象的映射
        - `hasParam`、`getParameter`、`getOptionalParameter`、`getParamOrNull` 可以通过 `ContextMap` 以不同的名称访问
        - `$Builder#withParameter`、`withOptionalParameter`、`getParameter`、`getOptionalParameter` 现在接受一个 `ContextKey` 而不是 `LootContextParam`
        - `$Builder#create` 现在接受一个 `ContextKeySet` 而不是 `LootContextParamSet`
    - `LootTable`
        - `getParameSet` 现在返回一个 `ContextKeySet` 而不是 `LootContextParamSet`
        - `$Builder#setParamSet` 现在接受一个 `ContextKeySet` 而不是 `LootContextParamSet`
    - `ValidationContext` 现在接受一个 `ContextKeySet` 而不是 `LootContextParamSet`
        - `validateUser` -> `validateContextUsage`
        - `setParams` - `setContextKeySet`
- `net.minecraft.world.level.storage.loot.functions`
    - `CopyComponentsFunction$Source#getReferencedContextParams` 现在接受一组 `ContextKey` 而不是一组 `LootContextParam`
- `net.minecraft.world.level.storage.loot.parameters`
    - `LootContextParam` -> `net.minecraft.util.context.ContextKey`
    - `LootContextParamSet` -> `net.minecraft.util.context.ContextKeySet`
- `net.minecraft.world.level.storage.loot.providers.nbt`
    - `ContextNbtProvider$Getter#getReferencedContextParams` 现在接受一组 `ContextKey` 而不是一组 `LootContextParam`
    - `NbtProvider#getReferencedContextParams` 现在接受一组 `ContextKey` 而不是一组 `LootContextParam`
- `net.minecraft.world.level.storage.loot.providers.score.ScoreboardNameProvider#getReferencedContextParams` 现在接受一组 `ContextKey` 而不是一组 `LootContextParam`

### 新增列表

- `com.mojang.blaze3d.framegraph`
    - `FrameGraphBuilder` - 一个构建帧图的构建器，定义渲染使用的资源和帧通道。
    - `FramePass` - 一个接口，定义如何在帧图内读取/写入资源并执行它们进行渲染。
- `com.mojang.blaze3d.platform`
    - `ClientShutdownWatchdog` - 为客户端关闭时创建的一个看门狗。
    - `NativeImage#getPixelsABGR` - 以 ABGR 格式获取图像的像素。
    - `Window`
        - `isIconified` - 返回窗口当前是否被图标化（通常最小化到任务栏）。
        - `setWindowCloseCallback` - 设置窗口关闭时要运行的回调。
- `com.mojang.blaze3d.resource`
    - `CrossFrameResourcePool` - 处理应跨多帧渲染的资源
    - `GraphicsResourceAllocator` - 处理要渲染和移除的资源。
    - `RenderTargetDescriptor` - 定义要分配和释放的渲染目标。
    - `ResourceDescriptor` - 定义一个资源以及如何分配和释放它。
    - `ResourceHandle` - 定义一个指向单个资源的指针。
- `com.mojang.blaze3d.systems.RenderSystem#overlayBlendFunc` - 设置具有透明度的层之间的默认覆盖混合函数。
- `com.mojang.blaze3d.vertex`
    - `PoseStack#translate(Vec3)` - 使用向量平移顶部姿势
    - `VertexConsumer#setNormal(PoseStack$Pose, Vec3)` - 使用向量设置顶点的法线
- `net.minecraft`
    - `Optionull#orElse` - 如果第一个对象为 null，则返回第二个对象。
    - `TracingExecutor` - 一个跟踪正在执行的类引用的堆栈帧的执行器。
    - `Util`
        - `allOf` - 对所有提供的谓词或谓词列表进行 AND 操作。如果没有提供谓词，该方法将默认为 `true`。
        - `anyOf` - 对所有提供的谓词或谓词列表进行 OR 操作。如果没有提供谓词，该方法将默认为 `false`。
        - `makeEnumMap` - 根据枚举类和一个将枚举转换为值的函数创建一个枚举映射。
- `net.minecraft.advancements.critereon`
    - `InputPredicate` - 一个匹配玩家正在进行的输入的谓词。
    - `SheepPredicate` - 用于实体是绵羊时的谓词。
- `net.minecraft.client`
    - `Minecraft`
        - `saveReport` - 将崩溃报告保存到给定文件。
        - `triggerResourcePackRecovery` - 当发生编译异常时尝试保存游戏的函数，目前在加载着色器时使用。
    - `Options#highContrastBlockOutline` - 启用时，在悬停在范围内方块上时提供更高的对比度。
    - `ScrollWheelHandler` - 一个用于在鼠标滚轮滚动时存储信息的处理器。
- `ItemSlotMouseAction` - 一个接口，定义鼠标悬停在槽位上时如何与槽位交互。
- `net.minecraft.client.gui.components`
    - `AbstractSelectionList#setSelectedIndex` - 根据索引设置选中的条目。
    - `AbstractWidget#playButtonClickSound` - 播放按钮点击声音。
    - `DebugScreenOverlay#getProfilerPieChart` - 获取饼图分析器渲染器。
- `net.minecraft.client.gui.components.debugchart.AbstractDebugChart#getFullHeight` - 返回渲染图表的高度。
- `net.minecraft.client.gui.components.toasts`
    - `Toast`
        - `getWantedVisbility` - 返回要渲染的吐司的可见性。
        - `update` - 更新吐司内的数据。
    - `TutorialToast` 有一个接受 `int` 表示显示时间（以毫秒为单位）的构造函数。
- `net.minecraft.client.gui.font.glyphs.BakedGlyph`
    - `renderChar` - 以指定颜色渲染一个字符。
    - `$GlyphInstance` - 一个带有其屏幕位置元数据的字形实例。
- `net.minecraft.client.gui.screens`
    - `BackupConfirmScreen` 有一个构造函数，接受另一个 `Component` 表示清除缓存的提示。
    - `Screen`
        - `getFont` - 返回当前用于渲染屏幕的字体。
        - `showsActiveEffects` - 当为 true 时，显示当前应用于玩家的状态效果，假设相关屏幕添加了该功能。
    - `net.minecraft.client.gui.screens.inventory`
    - `AbstractContainerScreen`
        - `BACKGROUND_TEXTURE_WIDTH`、`BACKGROUND_TEXTURE_HEIGHT` - 都设置为 256。
        - `addItemSlotMouseAction` - 当悬停在槽位上时添加鼠标动作。
        - `renderSlots` - 渲染菜单内的所有活动槽位。
    - `AbstractRecipeBookScreen` - 一个屏幕，具有从构造函数提供的可渲染和可交互的 `RecipeBookComponent`。
- `net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent#showTooltipWithItemInHand`- 返回当物品在玩家手中时是否应渲染工具提示。
- `net.minecraft.client.gui.screens.worldselection`
    - `CreateWorldCallback` - 一个接口，在给定当前屏幕、注册表、等级数据和路径目录的情况下创建世界。
    - `CreateWorldScreen#testWorld` - 尝试使用提供的生成设置上下文打开世界创建屏幕。
    - `InitialWorldCreationOptions` - 包含创建要生成的世界时设置的选项。
    - `WorldCreationContextMapper` - 一个接口，从可用的资源重载器和注册表创建世界上下文。
- `net.minecraft.client.multiplayer`
    - `ClientChunkCache`
        - `getLoadedEmptySections` - 返回已由游戏加载但没有数据的部分。
    - `ClientLevel`
        - `isTickingEntity` - 返回实体是否在等级中Tick。
        - `setSectionRangeDirty` - 将一个区域标记为脏，以便在持久性和网络调用期间更新。
        - `onSectionBecomingNonEmpty` - 当部分有数据时更新该部分。
    - `PlayerInfo#setTabListOrder`、`getTabListOrder` - 处理玩家标签页中循环切换玩家的顺序。
- `net.minecraft.client.multiplayer.chat.report.ReportReason#getIncompatibleCategories` - 获取对于给定类型无法报告的所有原因。
- `net.minecraft.client.particle.TrailParticle` - 一个从其当前位置到目标位置的拖尾粒子。
- `net.minecraft.client.player.LocalPlayer#getDropSpamThrottler` - 返回一个节流器，确定玩家何时可以丢弃下一个物品。
- `net.minecract.client.renderer`
    - `CloudRenderer` - 处理云纹理数据的渲染和加载。
    - `DimensionSpecialEffects#isSunriseOrSunset` - 返回维度时间是否代表游戏中的日出或日落。
    - `LevelEventHandler` - 处理由 `Level#levelEvent` 方法发送的事件。
    - `LevelRenderer`
        - `getCapturedFrustrum` - 返回渲染器的平截头体框。
        - `getCloudRenderer` - 返回天空盒中云的渲染器。
        - `onSectionBecomingNonEmpty` - 当部分有数据时更新该部分。
    - `LevelTargetBundle` - 保存渲染阶段的资源句柄和渲染目标。
    - `LightTexture`
        - `getBrightness` - 返回给定环境光和天空光的亮度。
        - `lightCoordsWithEmission` - 返回打包的光照坐标。
    - `RenderType`
        - `entitySolidZOffsetForward` - 获取一个实体的固体渲染类型，其中 z 从单个渲染对象偏移。
        - `flatClouds` - 获取平坦云的渲染类型。
        - `debugTriangleFan` - 获取调试三角形的渲染类型。
        - `vignette` - 获取晕影类型。
        - `crosshair` - 获取玩家准星的渲染类型。
        - `mojangLogo` - 获取 Mojang 徽标的渲染类型
    - `Octree` - 一个用于定义部分应在平截头体中渲染顺序的遍历实现。
    - `ShapeRenderer` - 用于在 Minecraft 等级中渲染基本形状的工具。
    - `SkyRenderer` - 渲染天空。
    - `WeatherEffectRenderer` - 渲染天气效果。
    - `WorldBorderRenderer` - 渲染世界边界。
- `net.minecraft.client.renderer`
    - `SectionOcclusionGraph#getOctree` - 返回用于处理渲染部分遍历的八叉树。
    - `ViewArea#getCameraSectionPos` - 获取相机的部分位置。
- `net.minecraft.client.renderer.culling.Frustum`
    - `getFrustumPoints` - 将平截头体矩阵作为 `Vector4f` 数组返回。
    - `getCamX`、`getCamY`、`getCamZ` - 返回平截头体相机坐标。
- `net.minecraft.client.renderer.chunk.CompileTaskDynamicQueue` - 一个处理块渲染部分编译任务的同步队列。
- `net.minecraft.client.renderer.debug`
    - `ChunkCullingDebugRenderer` - 用于当块被剔除时的调试渲染器。
    - `DebugRenderer`
        - `renderAfterTranslucents` - 在半透明渲染后渲染块剔除渲染器。
        - `renderVoxelShape` - 渲染体素形状的轮廓。
        - `toggleRenderOctree` - 切换是否渲染 `OctreeDebugRenderer`。
    - `OctreeDebugRenderer` - 渲染部分节点的顺序。
- `net.minecraft.client.renderer.texture.AbstractTexture#defaultBlur`、`getDefaultBlur` - 返回正在应用的模糊是否是默认模糊。
- `net.minecraft.client.resources.DefaultPlayerSkin#getDefaultSkin` - 返回默认的 `PlayerSkin`。
- `net.minecraft.commands.CommandBuildContext#enabledFeatures` - 返回功能标志
- `net.minecraft.commands.arguments.selector.SelectorPattern` - 一个记录，定义从某种模式解析的 `EntitySelector`。
- `net.minecraft.core`
    - `BlockPos#betweenClosed` - 返回边界框内所有位置的迭代器。
    - `Direction`
        - `getYRot` - 返回给定方向的 Y 旋转。
        - `getNearest` - 给定某个 XYZ 坐标，返回最近的方向，如果没有更近的方向则返回后备方向。
        - `getUnitVec3` - 返回法线单位向量。
        - `$Axis#getPositive`、`getNegative`、`getDirections` - 获取沿轴的方向。
    - `GlobalPos#isCloseEnough` - 返回此位置到另一个维度中块位置的距离是否在给定半径内。
    - `HolderLookup$Provider`
        - `listRegistries` - 返回每个注册表的注册表查找。
        - `allRegistriesLifecycle` - 返回所有注册表组合的生命周期。
    - `HolderSet#isBound` - 返回集合是否绑定到某个值。
    - `Registry$PendingTags#size` - 获取要加载的标签数量。
    - `Vec3i#distChessboard` - 获取向量分量之间的最大绝对距离。
- `net.minecraft.core.component`
    - `DataComponentHolder#getAllOfType` - 返回属于特定类类型的所有数据组件。
    - `DataComponentPredicate`
        - `someOf` - 构造一个数据组件谓词，其中提供的映射包含提供的组件类型。
        - `$Builder#expect` - 添加我们应该期望数据组件具有某个值。
    - `PatchedDataComponentMap#clearPatch` - 清除对象上数据组件的所有补丁。
- `net.minecraft.core.particles.TargetColorParticleOption` - 一个指定粒子目标位置和颜色的粒子选项。
- `net.minecraft.data.DataProvider`
    - `saveAll` - 使用提供的编解码器将资源位置到值的映射中的所有值写入 `PathProvider`。
    - `saveStable` - 使用给定的编解码器将值写入提供的路径。
- `net.minecraft.data.loot#BlockLootSubProvider`
    - `createMossyCarpetBlockDrops` - 为苔藓地毯块创建一个战利品表。
    - `createShearsOrSlikTouchOnlyDrop` - 创建一个只有在用剪刀或带有精准采集附魔的物品挖掘时才能掉落其物品的战利品表。
- `net.minecraft.data.worldgen.Pools#createKey` - 为模板池创建一个 `ResourceKey`。
- `net.minecraft.data.models.EquipmentModelProvider` - 装备模型的模型提供者，仅包含原版引导。
- `net.minecraft.data.info.DatapackStructureReport` - 一个返回数据包结构的提供者。
- `net.minecraft.gametest.framework`
    - `GameTestHelper`
        - `absoluteAABB`、`relativeAABB` - 在绝对坐标和相对于测试位置的坐标之间移动边界框
        - `assertEntityData` - 断言提供的块位置的实体匹配谓词。
        - `hurt` - 从某个来源对实体造成指定数量的伤害。
        - `kill` - 杀死实体。
    - `GameTestInfo#getTestOrigin` - 获取测试的生成结构的原点。
    - `StructureUtils#getStartCorner` - 获取要运行的测试的起始位置。
- `net.minecraft.network`
    - `FriendlyByteBuf`
        - `readVec3`、`writeVec3` - 读取和写入向量的静态方法。
        - `readContainerId`、`writeContainerId` - 读取和写入菜单标识符的方法。
        - `readChunkPos`、`writeChunkPos` - 读取和写入区块位置的方法。
    - `StreamCodec#composite` - 一个接受七个/八个参数的组合方法。
- `net.minecraft.network.codec.ByteBufCodecs`
    - `CONTAINER_ID` - 处理菜单标识符的流编解码器。
    - `ROTATION_BYTE` - 打包到字节中的旋转。
    - `LONG` - 长整型（64 字节）的流编解码器。
    - `OPTIONAL_VAR_INT` - 可选整数的流编解码器，当不存在时序列化 `0`，否则序列化存储值加一。
        - 使用此流编解码器无法正确发送 `-1`。
- `net.minecraft.network.protocol.game`
    - `ClientboundEntityPositionSyncPacket` - 一个同步实体位置的数据包。
    - `ClientboundPlayerRotationPacket` - 一个包含玩家旋转的数据包。
- `net.minecraft.server`
    - `MinecraftServer`
        - `tickConnection` - Tick连接以处理数据包。
        - `reportPacketHandlingException` - 报告尝试处理数据包时抛出的异常
        - `pauseWhileEmptySeconds` - 确定当没有玩家在线时服务器应暂停多少刻。
    - `SuppressedExceptionCollector` - 一个处理被服务器抑制的异常的处理器。
- `net.minecraft.server.commands.LookAt` - 一个接口，定义当命令运行时实体应该发生什么，通常是移动它以看向另一个实体。
- `net.minecraft.server.level`
    - `ChunkHolder#hasChangesToBroadcast` - 返回区块内是否有任何更新要发送给客户端。
    - `ChunkTaskDispatcher` - 区块的任务调度器。
    - `DistanceManager`
        - `getSpawnCandidateChunks` - 返回玩家可以生成的所有区块。
        - `getTickingChunks` - 返回当前正在Tick的所有区块。
    - `ServerChunkCache#onChunkReadyToSend` - 将一个区块持有者添加到队列中进行广播。
    - `ServerEntityGetter` - 一个在 `ServerLevel` 上操作的实体获取器接口实现。
        - 替换了 `EntityGetter` 中缺失的方法
    - `ServerPlayer`
        - `getTabListOrder` - 处理玩家标签页中循环切换玩家的顺序。
        - `getLastClientInput`、`setLastClientInput`、`getLastClientMoveIntent` - 处理服务器玩家如何解释客户端脉冲。
        - `commandSource` - 返回玩家的命令源。
        - `createCommandSourceStack` - 创建发出命令的玩家的源堆栈。
    - `ThrottlingChunkTaskDispatcher` - 一个设置最大同时执行区块数的区块任务调度器。
    - `TickingTracker#getTickingChunks` - 返回当前正在Tick的所有区块。
- `net.minecraft.server.packs.repository.PackRepository#isAbleToClearAnyPack` - 重建选定的资源包并返回它是否与当前选定的资源包不同。
- `net.minecraft.resources.DependantName` - 一个将某个注册表对象 `ResourceKey` 映射到一个值的引用对象。类似于 `Holder`，但作为一个函数式接口。
- `net.minecraft.tags.TagKey#streamCodec` - 为标签键构造一个流编解码器。
- `net.minecraft.util`
    - `ARGB#vector3fFromRGB24` - 使用整数的低 24 位创建一个包含 RGB 分量的 `Vector3f`。
    - `BinaryAnimator` - 一个使用缓动函数在两个状态之间进行动画的基本动画器。
    - `ExtraCodecs`
        - `NON_NEGATIVE_FLOAT` - 一个验证值不能为负的浮点编解码器。
        - `RGB_COLOR_CODEC` - 一个表示 RGB 颜色的整数、浮点数或三维向量浮点编解码器。
        - `nonEmptyMap` - 一个验证映射不为空的映射编解码器。
    - `Mth`
        - `wrapDegrees` - 将度数设置为 (-180, 180] 范围内的值。
        - `lerp` - 使用分量在两个向量之间进行线性插值。
        - `length` - 获取空间中 2D 点的长度。
        - `easeInOutSine` - 一个从 (0,0) 开始，每 pi 在 1 和 0 之间交替的余弦函数。
        - `packDegrees`、`unpackDegrees` - 将 `float` 形式的度数存储到 `byte` 中并读取。
    - `RandomSource#triangle` - 使用三角形分布在两个 `float`（包含，不包含）之间返回一个随机的 `float`。
    - `StringRepresentable$EnumCodec#byName` - 通过字符串名称获取枚举，如果为 null 则获取提供的供应商值。
    - `TriState` - 一个表示三种可能状态的枚举：true、false 或 default。
- `net.minecraft.util.datafix.ExtraDataFixUtils`
    - `patchSubType` - 将第一个类型中的第二个类型重写为第三个类型。
    - `blockState` - 返回方块状态的动态实例
    - `fixStringField` - 修改动态中的字符串字段。
- `net.minecraft.util.thread.BlockableEventLookup`
    - `BLOCK_TIME_NANOS` - 返回事件将阻塞线程的时间（以纳秒为单位）。
    - `isNonRecoverable` - 返回异常是否可以恢复。
- `net.minecraft.world.damagesource.DamageSources`
    - `enderPearl` - 返回末影珍珠击中时的伤害来源。
    - `mace` - 返回一个实体直接用狼牙棒击中另一个实体时的伤害来源。
- `net.minecraft.world.entity`
    - `Entity`
        - `applyEffectsFromBlocks` - 通过 `Block#entityInside` 或硬编码检查（如雪或雨）应用方块产生的任何效果。
        - `isAffectedByBlocks` - 返回实体在内部时是否受方块影响。
        - `checkInsideBlocks` - 获取玩家经过的所有方块，并检查实体是否在一个方块内，如果存在则将其添加到一个集合中。
        - `oldPosition`、`setOldPosAndrot`、`setOldPos`、`setOldRot` - 更新实体最后位置和旋转的辅助方法。
        - `getXRot`、`getYRot` - 返回给定部分刻下实体的线性插值旋转。
        - `isAlliedTo(Entity)` - 返回实体是否与此实体结盟。
        - `teleportSetPosition` - 通过 `DimensionTransition` 设置被传送实体的位置和旋转数据
        - `getLootTable` - 返回实体应使用的战利品表的 `ResourceKey`（如果存在）。
        - `isControlledByOrIsLocalPlayer` - 返回实体是否是本地玩家或由本地玩家控制。
        - `shouldPlayLavaHurtSound` - 当为 `true` 时，实体受到熔岩伤害时播放熔岩伤害声音。
        - `onRemoval` - 当实体被移除时调用的方法。
        - `cancelLerp` - 停止任何插值移动。
        - `forceSetRotation` - 设置实体的旋转。
        - `isControlledByClient` - 返回实体是否由客户端输入控制。
    - `EntityType`
        - `getDefaultLootTable` 现在返回一个 `Optional`，以防战利品表不存在
        - `$Builder#noLootTable` - 设置实体类型在死亡时不生成战利品。
        - `$Builder#build` 现在接受实体类型的资源键
    - `EntitySelector#CAN_BE_PICKED` - 返回一个选择器，获取所有不在旁观模式下的可拾取实体。
    - `LivingEntity`
        - `dropFromShearingLootTable` - 使用剪毛上下文解析战利品表。
        - `getItemHeldByArm` - 返回特定手臂持有的堆栈。
        - `getEffectiveGravity` - 返回应用于实体的重力。
        - `canContinueToGlide` - 返回实体是否仍能在空中滑翔。
        - `getItemBlockingWith` - 返回玩家当前正在格挡的堆栈。
        - `canPickUpLoot` - 返回实体是否可以拾取物品。
        - `dropFromGiftLootTable` - 使用礼物上下文解析战利品表。
        - `handleExtraItemsCreatedOnUse` - 处理活体实体因使用另一个物品而获得新物品时的情况。
        - `isLookingAtMe` - 检查提供的实体是否正在看着这个实体。
    - `PositionMoveRotation` - 用于处理上下文中实体的位置和旋转的辅助工具。
    - `WalkAnimationState#stop` - 停止实体的行走动画。
- `net.minecraft.world.entity.ai.attributes`
    - `AttributeInstance`
        - `getPermanentModifiers` - 返回应用于实体的所有永久修饰符。
        - `addPermanentModifiers` - 添加一组要应用的永久修饰符。
    - `AttributeMap#assignPermanentModifiers` - 从另一个映射复制永久修饰符。
- `net.minecraft.world.entity.ai.control.Control#rotateTowards` - 返回一个浮点数，通过提供的差值在钳制值内旋转到某个最终旋转。
- `net.minecraft.world.entity.ai.goal.Goal#getServerLevel` - 根据实体或等级获取服务器等级。
- `net.minecraft.world.entity.ai.navigation.PathNavigation`
    - `updatePathfinderMaxVisitedNodes` - 更新实体可以访问的最大节点数。
    - `setRequiredPathLength` - 设置实体必须采取的最小路径长度。
    - `getMaxPathLength` - 返回实体可以采取的最大路径长度。
- `net.minecraft.world.entity.ai.sensing`
    - `PlayerSensor#getFollowDistance` - 返回此实体的跟随距离。
    - `Sensor#wasEntityAttackableLastNTicks` - 返回一个谓词，检查实体在指定的刻数内是否可攻击。
- `net.minecraft.world.entity.ai.village.poi.PoiRecord#pack`、`PoiSection#pack` - 打包必要的兴趣点信息。这只移除了脏 runnable。
- `net.minecraft.world.entity.animal`
    - `AgeableWaterCreature` - 一个有年龄状态的水生生物。
    - `Animal`
        - `createAnimalAttributes` - 为动物创建属性提供者。
        - `playEatingSound` - 播放动物在进食时发出的声音。
    - `Bee#isNightOrRaining` - 返回当前等级是否有天空光，并且是夜晚或下雨。
    - `Cat#isLyingOnTopOfSleepingPlayer` - 返回猫是否在睡觉的玩家身上。
    - `Salmon#getSalmonScale` - 返回应用于实体边界框的缩放因子。
    - `Wolf#DEFAULT_TAIL_ANGLE` - 返回狼的默认尾巴角度。
- `net.minecraft.world.entity.boss.enderdragon.DragonFlightHistory` - 保存龙在天空飞行时的 Y 轴和旋转。用于更好地动画龙身体部位的运动。
- `net.minecraft.world.entity.monster.Zombie#canSpawnInLiquids` - 当为 true 时，僵尸可以在液体中生成。
- `net.minecraft.world.entity.player`
    - `Inventory`
        - `isUsableForCrafting` - 返回状态是否可以用于合成配方。
        - `createInventoryUpdatePacket` - 创建用于更新库存中物品的数据包。
    - `Player`
        - `handleCreativeModeItemDrop` - 处理玩家从创造模式丢弃物品时的情况。
        - `shouldRotateWithMinecart` - 返回玩家是否也应随矿车旋转。
        - `canDropItems` - 当为 `true` 时，玩家可以从菜单中丢弃物品。
        - `getPermissionLevel`、`hasPermissions` - 返回玩家的权限。
    - `StackedContents` - 保存内容列表及其关联大小。
        - `$Output` - 一个接口，定义在选择内容时如何接受它们。
- `net.minecraft.world.entity.projectile.Projectile`
    - `spawnProjectileFromRotation` - 生成一个投射物并从给定的旋转角度射出。
    - `spawnProjectileUsingShoot` - 生成一个投射物并通过 `#shoot` 设置初始冲量。
    - `spawnProjectile` - 生成一个投射物。
    - `applyOnProjectileSpawned` - 根据给定的等级和 `ItemStack` 应用任何额外的配置。
    - `onItemBreak` - 处理发射投射物的物品损坏时的情况。
    - `shouldBounceOnWorldBorder` - 返回投射物是否应弹离世界边界。
    - `setOwnerThroughUUID` - 通过查询其 UUID 来设置投射物的拥有者。
    - `$ProjectileFactory` - 定义投射物如何从某个 `ItemStack` 由实体生成。
- `net.minecraft.world.entity.vehicle`
    - `AbstractBoat` - 一个代表船的实体。
    - `AbstractChestBoat` - 一个代表带有某种库存的船的实体。
    - `ChestRaft` - 一个代表带有某种库存的木筏的实体。
    - `Raft` - 一个代表木筏的实体。
- `net.minecraft.world.inventory.AbstractContainerMenu`
    - `addInventoryHotbarSlots` - 在给定的 x 和 y 位置为给定容器添加快捷栏槽位。
    - `addInventoryExtendedSlots` - 在给定的 x 和 y 位置为给定容器添加玩家库存槽位。
    - `addStandardInventorySlots` - 在给定的 x 和 y 位置为给定容器在其正常位置添加快捷栏和玩家库存槽位。
    - `setSelectedBundleItemIndex` - 切换槽位中选中的捆绑包。
- `net.minecraft.world.item`
    - `BundleItem`
        - `getOpenBundleModelFrontLocation`、`getOpenBundleModelBackLocation` - 返回捆绑包的模型位置。
        - `toggleSelectedItem`、`hasSelectedItem`、`getSelectedItem`、`getSelectedItemStack` - 处理捆绑包内的物品选择。
        - `getNumberOfItemsToShow` - 确定一次显示的捆绑包中的物品数量。
        - `getByColor` - 处理从捆绑包到染色捆绑包的可用链接。
        - `getAllBundleItemColors` - 返回所有染色捆绑包的流。
    - `ItemStack`
        - `clearComponents` - 清除对堆栈所做的补丁，而不是物品组件。
        - `isBroken` - 返回堆栈是否已损坏。
        - `hurtWithoutBreaking` - 损坏堆栈而不使其损坏。
        - `getStyledHoverName` - 获取堆栈的样式化名称组件。
- `net.minecraft.world.item.component.BundleContents`
    - `canItemBeInBundle` - 物品是否可以放入捆绑包。
    - `getNumberOfItemsToShow` - 确定一次显示的捆绑包中的物品数量。
    - `hasSelectedItem`、`getSelectedItem` - 处理捆绑包内的物品选择。
- `net.minecraft.world.item.enchantment.EnchantmentHelper`
    - `createBook` - 创建一个附魔书堆栈。
    - `doPostAttackEffectsWithItemSourceOnBreak` - 在物品损坏时，在攻击后应用附魔。
- `net.minecraft.world.level`
    - `BlockCollisions` 有一个接受 `CollisionContext` 的构造函数
    - `BlockGetter#boxTraverseBlocks` - 返回在给定边界框中沿向量遍历的位置的迭代器。
    - `CollisionGetter`
        - `noCollision` - 返回实体与方块、实体以及如果提供的 `boolean` 为 `true` 则液体之间是否存在碰撞。
        - `getBlockAndLiquidCollisions` - 返回边界框内实体的方块和液体碰撞。
        - `clipIncludingBorder` - 获取指定剪辑上下文的方块命中结果，必要时由世界边界钳制。
    - `EmptyBlockAndTintGetter` - 一个虚拟的 `BlockAndTintGetter` 实例。
    - `GameType#isValidId` - 检查 id 是否与现有的游戏类型匹配。
    - `LevelHeightAccessor#isInsideBuildHeight` - 返回指定的 Y 坐标是否在等级的边界内。
- `net.minecraft.world.level.block`
    - `Block#UPDATE_SKIP_SHAPE_UPDATE_ON_WIRE` - 一个方块标志，当启用时，不更新红石线的形状。
    - `BonemealableFeaturePlacerBlock` - 一个放置配置功能并可以施骨粉的方块。
- `net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerData#resetStatistics` - 将生成的数据重置为空设置，但不清除当前生物或下一个生成实体。
- `net.minecraft.world.level.block.piston.PistonMovingBlockEntity#getPushDirection` - 返回移动活塞的推动方向。
- `net.minecraft.world.level.block.state`
    - `BlockBehaviour`
        - `getEntityInsideCollisionShape`、`$BlockStateBase#getEntityInsideCollisionShape` - 确定实体在内部时方块的体素形状。
        - `$Properties#overrideDescription` - 设置方块名称的翻译键。
    - `StateHolder`
        - `getValueOrElse` - 返回属性的值，否则返回提供的默认值。
        - `getNullableValue` - 返回属性的值，如果不存在则返回 null。
- `net.minecraft.world.level.block.state.properties.Property#getInternalIndex` - 当为 true 时将提供的布尔值转换为 0，否则转换为 1。
- `net.minecraft.world.level.border.WorldBorder#clampVec3ToBound` - 将向量钳制在世界边界内。
- `net.minecraft.world.level.chunk`
    - `ChunkAccess#canBeSerialized` - 返回 true，允许将区块写入磁盘。
    - `ChunkSource#onSectionEmptinessChanged` - 当部分有数据时更新该部分。
    - `LevelChunkSection`
        - `copy` - 制作区块部分的浅拷贝。
        - `setUnsavedListener` - 添加一个监听器，每当区块被标记为脏时，该监听器接受区块位置。
        - `$UnsavedListener` - 一个当区块被标记为脏时被调用的区块位置消费者。
    - `PalettedContainerRO#copy` - 创建 `PalettedContainer` 的浅拷贝。
    - `UpgradeData#copy` - 创建 `UpgradeData` 的深拷贝。
- `net.minecraft.world.level.chunk.storage.IOWorker#store` - 将区块的写入存储到工作器中。
- `net.minecraft.world.level.levelgen`
    - `SurfaceRules$Context#getSeaLevel`、`SurfaceSystem#getSeaLevel` - 获取生成器设置的海平面。
    - `WorldOptions#testWorldWithRandomSeed` - 使用随机生成的种子创建一个测试世界。
- `net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecorator$Context#checkBlock` - 检查给定位置的方块是否匹配谓词。
- `net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate`
    - `getJigsaws` - 返回在给定位置和旋转下具有给定旋转的拼图方块。
    - `getJointType` - 返回拼图方块的连接类型。
    - `$JigsawBlockInfo` - 一个包含拼图方块块信息的记录。
        - 大多数涉及拼图的方法已将 `$StructureBlockInfo` 替换为 `$JigsawBlockInfo`。
- `net.minecraft.world.level.lighting.LayerLightSectionStorage#lightOnInColumn` - 返回零节点部分位置是否有光。
- `net.minecraft.world.level.pathfinder.PathFinder#setMaxVisitedNodes` - 设置可以访问的最大节点数。
- `net.minecraft.world.level.portal`
    - `DimensionTransition#withRotation` - 更新实体的生成旋转。
    - `PortalShape#findAnyShape` - 找到一个可以位于给定方块位置并面向特定方向的 `PortalShape`。
- `net.minecraft.world.phys`
    - `AABB`
        - `clip` - 在给定边界框内剪辑向量，如果没有交点则返回空 optional。
        - `collidedAlongVector` - 返回此框是否与列表中提供的边界框之一沿提供的移动向量发生碰撞。
        - `getBottomCenter` - 获取边界框底部中心的向量。
    - `Vec3`
        - `add`、`subtract` - 平移向量并返回一个新对象。
        - `horizontal` - 返回向量的水平分量。
        - `projectedOn` - 获取表示此向量投影到另一个向量上的单位向量。
- `net.minecraft.world.phys.shapes`
    - `CollisionContext`
        - `of(Entity, boolean)` - 创建一个新的实体碰撞上下文，其中 `boolean` 确定实体是否总是可以站在提供的流体状态上。
        - `getCollisionShape` - 返回碰撞到的碰撞形状。
    - `VoxelShape#move(Vec3)` - 将体素形状按提供的向量偏移。
- `net.minecraft.world.ticks.ScheduledTick#toSavedTick` - 将计划Tick转换为保存的Tick。

### 变更列表

- `F3 + F` 现在切换雾渲染
- `com.mojang.blaze3d.platform`
    - `NativeImage`
        - `getPixelRGBA`、`setPixelRGBA` 现在是私有的。它们分别被 `getPixel` 和 `setPixel` 取代
        - `getPixelsRGBA` -> `getPixels`
    - `Window#updateDisplay` 现在接受一个 `TraceyFrrameCapture`，或 `null`
- `net.minecraft.Util`
    - `backgroundExecutor`、`ioPool` 和 `nonCriticalIoPool` 现在返回 `TracingExecutor` 而不是 `ExecutorService`
    - `wrapThreadWithTaskName` -> `runNamed`，参数翻转，无返回值
- `net.minecraft.advancements.critereon`
    - `KilledByCrossbowTrigger` -> `KilledByArrowTrigger`，不是一对一，接受相关的堆栈
    - `PlayerPredicate` 现在可以匹配玩家的输入
- `net.minecraft.client`
    - `Minecraft`
        - `debugFpsMeterKeyPress` -> `ProfilerPieChart#profilerPieChartKeyPress`，通过 `Minecraft#getDebugOverlay` 然后 `DebugScreenOverlay#getProfilerPieChart` 获得
        - `getTimer` -> `getDeltaTracker`
        - `getToasts` -> `getToastManager`
    - `Options#setModelPart` 现在是公开的，取代了 `toggleModelPart` 但不广播更改
    - `ParticleStatus` -> `net.minecraft.server.level.ParticleStatus`
- `net.minecraft.client.animation.KeyframeAnimations#animate` 现在接受一个 `Model` 而不是 `HierarchicalModel`
- `net.minecraft.client.gui.Font`
    - `drawInBatch(String, float, float, int, boolean, Matrix4f, MultiBufferSource, Font.DisplayMode, int, int, boolean)` 已移除，应使用 `Component` 替代
        - 还有一个委托，在 `Component` 的 `drawInBatch` 方法中默认将逆深度布尔值设置为 true
    - `$StringRenderOutput` 现在接受 `Font`、一个可选背景颜色，以及一个布尔值，表示在绘制文本时是否应使用逆深度
    - `$StringRenderOutput#finish` 现在是包私有的
- `net.minecraft.client.gui.components`
    - `AbstractSelectionList`
        - `replaceEntries` 现在是公开的
        - `getRowTop`、`getRowBottom` 现在是公开的
    - `PlayerFaceRenderer#draw(GuiGraphics, ResourceLocation, int, int, int, int)` 接受一个 `PlayerSkin` 而不是 `ResourceLocation`
- `net.minecraft.client.gui.components.toasts`
    - `Toast`
        - `Toast$Visibility render(GuiGraphics, ToastComponent, long)` -> `void render(GuiGraphics, Font, long)`
        - `slotCount` - `occupiedSlotCount`
    - `ToastComponent` -> `ToastManager`
- `net.minecraft.client.gui.font.glyphs.BakedGlyph`
    - `render` 现在接受一个表示颜色的整数而不是四个浮点数，并且是私有的
        - `renderChar` 是公共替代，接受 `$GlyphInstance`、`Matrix4f`、`VertexConsumer` 和颜色整数
    - `$Effect` 是一个记录，现在接受一个表示颜色的整数而不是四个浮点数
- `net.minecraft.client.gui.screens`
    - `LoadingOverlay#MOJANG_STUDIOS_LOGO_LOCATION` 现在是公开的
    - `Screen`
        - `renderBlurredBackground(float)` -> `renderBlurredBackground()`
        - `wrapScreenError` -> `fillCrashDetails`，不是一对一，因为它只添加相关的崩溃信息，而不是实际抛出错误
- `net.minecraft.client.gui.screens.inventory`
    - `AbstractContainerScreen#renderSlotHighlight` -> `renderSlotHighlightBack`、`renderSlotHighlightFront`，现在是私有的
    - `BookEditScreen` 现在接受 `WritableBookContent`
    - `AbstractSignEditScreen`
        - `sign` 现在是 protected
        - `renderSignBackground` 不再接受 `BlockState`
    - `EffectRenderingInventoryScreen` -> `Screen#hasActiveEffects`、`EffectsInInventory`。不是一对一，因为 `EffectsInInventory` 现在作为一个辅助类，帮助屏幕在指定位置渲染其效果。
- `net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent`
    - `getHeight()` -> `getHeight(Font)`
    - `renderImage` 现在接受渲染工具提示的 `int` 宽度和高度
- `net.minecraft.client.gui.screens.recipebook`
    - `GhostSlots#render` 不再接受 x 和 y 偏移。
    - `RecipeBookComponent` 不再接受 x 和 y 偏移。
- `net.minecraft.client.gui.screens.reporting.ReportReasonSelectionScreen` 现在接受一个 `ReportType`
- `net.minecraft.client.gui.screens.worldselection`
    - `CreateWorldScreen`
        - `$DataPackReloadCookie` -> `DataPackReloadCookie`
        - `openFresh` 现在有一个接受 `CreateWorldCallback` 的重载
    - `WorldCreationContext` 现在接受 `InitialWorldCreationOptions`
    - `WorldOpenFlows#createFreshLevel` 接受一个 `Function<HolderLookup.Provider, WorldDimensions>` 而不是 `Function<RegistryAccess, WorldDimensions>`
- `net.minecraft.client.gui.spectator.SpectatorMenuItem#renderIcon` 现在接受一个 `float` 而不是 `int` 来表示 alpha 值
- `net.minecraft.client.multiplayer`
    - `ClientLevel` 现在接受一个 `int` 表示海平面
        - `getSkyColor` 现在返回一个 `int` 而不是 `Vec3`
        - `getCloudColor` 现在返回一个 `int` 而不是 `Vec3`
        - `setGameTime`、`setDayTime` -> `setTimeFromServer`
    - `TagCollector` -> `RegistryDataCollector$TagCollector`，现在是包私有的
- `net.minecraft.client.player`
    - `AbstractClientPlayer#getFieldOfViewModifier` 现在接受一个布尔值表示相机是否在第一人称，以及一个浮点数表示部分刻
    - `Input` -> `ClientInput` 和 `net.minecraft.world.entity.player.Input`
    - `KeyboardInput` 现在继承 `ClientInput`
    - `LocalPlayer#input` 现在是 `ClientInput`
- `net.minecraft.client.renderer`
    - `DimensionSpecialEffects#getSunriseColor` -> `getSunriseOrSunsetColor`
    - `GameRenderer`
        - `processBlurEffect` 不再接受部分刻 `float`
        - `getFov` 返回 `float` 而不是 `double`
        - `getProjectionMatrix` 现在接受 `float` 而不是 `double`
    - `ItemModelShaper`
        - `shapes` 现在是私有的
        - `getItemModel(Item)` 已移除
        - `getItemModel(ResourceLocation)` - 获取与提供的 `ResourceLocation` 关联的烘焙模型。
        - `register` 已移除
        - `getModelManager` 已移除
        - `invalidateCache` - 清除模型映射。
    - `LevelRenderer`
        - `renderSnowAndRain` -> `WeatherEffectRenderer`
        - `tickRain` -> `tickParticles`
        - `renderLevel` 现在接受一个 `GraphicsResourceAllocator`
        - `renderClouds` -> `CloudRenderer`
        - `addParticle` 现在是公开的
        - `globalLevelEvent` -> `LevelEventHandler`
        - `entityTarget` -> `entityOutlineTarget`
        - `$TransparencyShaderException` 不再接受可抛出原因
    - `SectionOcclusionGraph`
        - `onSectionCompiled` -> `schedulePropagationFrom`
        - `update` 现在接受一个保存当前加载的部分节点的 `LongOpenHashSet`
        - `$GraphState` 现在是包私有的
        - `addSectionsInFrustum` 现在接受一个列表以添加渲染部分
    - `ShapeRenderer#renderShape` 现在接受一个整数表示颜色，而不是四个浮点数
    - `ViewArea`
        - `repositionCamera` 现在接受 `SectionPos` 而不是两个 `double`
        - `getRenderSectionAt` -> `getRenderSection`
- `net.minecraft.client.renderer.blockentity`
    - `BannerRenderer#renderPatterns` 现在接受一个 `boolean` 确定要使用的闪光渲染类型
    - 构造 `LayerDefinition` 的 `*Renderer` 类现在已移动到它们关联的 `*Model` 类
    - `SignRenderer$SignModel` -> `SignModel`
- `net.minecraft.client.renderer.chunk.SectionRenderDispatcher` 现在接受一个 `TracingExecutor` 而不是仅仅一个 `Executor`
    - `$CompiledSection#hasNoRenderableLayers` -> `hasRenderableLayers`
    - `$RenderSection` 现在接受一个编译的 `long` 表示部分节点
        - `setOrigin` -> `setSectionNode`
        - `getRelativeOrigin` -> `getNeighborSectionNode`
        - `cancelTasks` 现在不返回任何内容
        - `pointOfView` - 一个指向半透明渲染类型渲染位置的引用。
        - `resortTransparency` 不再接受 `RenderType` 并且不返回任何内容
        - `hasTranslucentGeometry` - 返回编译的方块是否具有半透明渲染类型。
        - `transparencyResortingScheduled` - 返回最后一个任务是否已调度但未完成。
        - `isAxisAlignedWith` -> `$TranslucencyPointOfView#isAxisAligned`
    - `$CompileTask` 现在是公开的
        - 不再实现 `Comparable`
        - 构造函数不再接受创建时的距离
        - `isHighPriority` -> `isRecompile`
    - `$TranslucencyPointOfView` - 返回表示此部分中半透明渲染类型视图点的坐标。
- `net.minecraft.client.renderer.culling.Frustum#cubeInFrustum` 现在返回一个 `int`，表示剔除该框的第一个平面的索引
- `net.minecraft.client.renderer.DebugRenderer#render` 现在接受 `Frustum`
- `net.minecraft.client.renderer.texture.atlas.sources.PalettedPermutations#loadPaletteEntryFromImage` 现在是私有的
- `net.minecraft.client.tutorial`
    - `Tutorial`
        - `addTimedToast`、`#removeTimedToast`、`$TimedToast` -> `TutorialToast` 参数
        - `onInput` 接受一个 `ClientInput` 而不是 `Input`
    - `TutorialStepInstance`
        - `onInput` 接受一个 `ClientInput` 而不是 `Input`
- `net.minecraft.core`
    - `Direction`
        - `getNearest` -> `getApproximateNearest`
        - `getNormal` -> `getUnitVec3i`
    - `HolderGetter$Provider#get` 不再接受注册表键，而是从 `ResourceKey` 读取它
    - `HolderLookup$Provider` 现在实现 `HolderGetter$Provider`
        - `asGetterLookup` 已移除，因为该接口是一个 `HolderGetter$Provider`
        - `listRegistries` -> `listRegistryKeys`
    - `Registry` 现在实现 `HolderLookup$RegistryLookup`
        - `getTags` 只返回命名持有者集的流
        - `asTagAddingLookup` -> `prepareTagReload`
        - `bindTags` -> `WritabelRegistry#bindTag`
        - `get` -> `getValue`
        - `getOrThrow` -> `getValueOrThrow`
        - `getHolder` -> `get`
        - `getHolderOrThrow` -> `getOrThrow`
        - `holders` -> `listElements`
        - `getTag` -> `get`
        - `holderOwner`、`asLookup` 已移除，因为 `Registry` 是它们的实例
    - `RegistryAccess`
        - `registry` -> `lookup`
        - `registryOrThrow` -> `lookupOrThrow`
    - `RegistrySynchronization#NETWORKABLE_REGISTRIES` -> `isNetworkable`
- `net.minecraft.core.cauldron.CauldronInteraction`
    - `FILL_WATER` -> `fillWaterInteraction`，现在是私有的
    - `FILL_LAVA` -> `fillLavaInteraction`，现在是私有的
    - `FILL_POWDER_SNOW` -> `fillPowderSnowInteraction`，现在是私有的
    - `SHULKER_BOX` -> `shulkerBoxInteraction`，现在是私有的
    - `BANNER` -> `bannerInteraction`，现在是私有的
    - `DYED_ITEM` -> `dyedItemIteration`，现在是私有的
- `net.minecraft.core.dispenser.BoatDispenseItemBehavior` 现在接受要生成的 `EntityType` 而不是变体和是否有箱子的布尔值
- `net.minecraft.core.particles.DustColorTransitionOptions`、`DustParticleOptions` 现在接受表示 RGB 值的整数而不是 `Vector3f`。
- `net.minecraft.data.loot`
    - `BlockLootSubProvider`
        - `HAS_SHEARS` -> `hasShears`
        - `createShearsOnlyDrop` 现在是一个实例方法
    - `EntityLootSubProvider`
        - `killedByFrog`、`killedByFrogVariant` 现在接受 `EntityType` 注册表的获取器
        - `createSheepTable` -> `createSheepDispatchPool`，不是一对一，因为该表被替换为一个池构建器，给定一个染料颜色到战利品表的映射
- `net.minecraft.gametest.framework`
    - `GameTestHelper#assertEntityPresent`、`assertEntityNotPresent` 接受一个边界框而不是两个向量
    - `GameTestInfo#getOrCalculateNorthwestCorner` 现在是公开的
- `net.minecraft.network.chat.Component#score` 现在接受一个 `SelectorPattern`
- `net.minecraft.network.chat.contents.ScoreContents`、`SelectorContents` 现在是一个记录
- `net.minecraft.network.protocol.login.ClientboundGameProfilePacket` -> `ClientboundLoginFinishedPacket`
- `net.minecraft.network.protocol.game`
    - `ClientboundMoveEntityPacket#getyRot`、`getxRot` 现在返回一个 `float` 表示度数
    - `ClientboundPlayerPositionPacket` 现在是一个记录，接受一个表示变化的 `PositionMoverotation`
        - `relativeArguments` -> `relatives`
        - `yRot`、`xRot` -> `ClientboundPalyerRotationPacket`
    - `ClientboundSetTimePacket` 现在是一个记录
    - `ClientboundRotateHeadPacket#getYHeadRot` 现在返回一个 `float` 表示度数
    - `ClientboundTeleportEntityPacket` 现在是一个记录，其中必要的参数被传入数据包而不是实体
    - `ServerboundPlayerInputPacket` 现在是一个记录，接受一个 `Input`
- `net.minecraft.resources.RegistryDataLoader$Loader#loadFromNetwork` 现在接受一个 `$NetworkedRegistryData`，其中包含打包的注册表条目
- `net.minecraft.server`
    - `MinecraftServer` 不再实现 `AutoCloseable`
        - `tickChildren` 现在是 protected
        - `wrapRunnable` 现在是公开的
    - `ReloadableServerRegistries#reload` 现在接受一个待处理标签的列表，并返回一个 `$LoadResult` 而不是一个分层注册表访问
    - `ReloadableServerResources`
        - `loadResources` 现在接受一个待处理标签的列表和服务器 `Executor`
        - `updateRegistryTags` -> `updateStaticRegistryTags`
    - `ServerFunctionLibrary#getTag`、`ServerFunctionManager#getTag` 返回一个命令函数列表
- `net.minecraft.server.level`
    - `ChunkHolder`
        - `blockChanged`、`sectionLightChanged` 现在返回 `boolean` 表示信息是否已更改
        - `addSaveDependency` 现在是 protected，`GenerationChunkHolder` 中的一个方法
    - `ChunkTaskPriorityQueue` 不再接受泛型
        - 构造函数不再接受最大任务数
        - `submit` 现在接受一个 `Runnable` 而不是 `Optional`
        - `pop` 返回一个 `$TasksForChunk` 而不是原始的 `Stream`
    - `ChunkTaskPriorityQueueSorter` -> `ChunkTaskDispatcher`
    - `ServerPlayer`
        - `teleportTo` 接受一个 `boolean`，决定是否应设置相机
        - `INTERACTION_DISTANCE_VERIFICATION_BUFFER` -> `BLOCK_INTERACTION_DISTANCE_VERIFICATION_BUFFER`
            - 还拆分为 `ENTITY_INTERACTION_DISTANCE_VERIFICATION_BUFFER`，设置为 3.0
        - `findRespawnPositionAndUseSpawnBlock` 现在处理 `TeleportTransition`
    - `TextFilterClient` -> `ServerTextFilter`
    - `ThreadedLevelLightEngine` 现在接受一个 `ConsecutiveExecutor` 和 `ChunkTaskDispatcher` 而不是分别接受 `ProcessorMailbox` 和 `ProcessorHandle`
- `net.minecraft.server.packs.resources.ProfiledReloadInstance$State` 现在是一个记录
- `net.minecraft.sounds.SoundEvent` 现在是一个记录
- `net.minecraft.tags`
    - `TagEntry$Lookup#element` 现在接受一个 `boolean` 表示元素是否必需
    - `TagLoader` 现在接受一个 `$ElementLookup`，其功能与之前的函数参数相同
        - `build` 现在返回一个列表的值
        - `loadAndBuild` -> `loadTagsFromNetwork`、`loadTagsForExistingRegistries`、`loadTagsForRegistry`、`buildUpdatedLookups`
    - `TagNetworkSerialization$NetworkPayload`
        - `size` -> `isEmpty`
        - `applyToRegistry` -> `resolve`
- `net.minecraft.util`
    - `FastColor` -> `ARGB`
        - `scaleRGB` 重载，带有一个 alpha 整数和三个浮点数。
    - `Mth#color` -> `ARGB#color`
- `net.minecraft.util.profiling.metrics.MetricCategory#MAIL_BOXES` -> `CONSECUTIVE_EXECUTORS`
- `net.minecraft.util.thread`
    - `BlockableEventLoop#waitForTasks` 现在是 protected
    - `ProcessorMailbox` 不再实现 `AutoCloseable`
- `net.minecraft.util.worldupdate.WorldUpgrader` 实现 `AutoCloseable`
- `net.minecraft.world.LockCode` 现在接受一个 `ItemPredicate` 而不是表示物品名称的 `String`
    - `addToTag`、`fromTag` 现在接受一个 `HolderLookup$Provider`
- `net.minecraft.world.effect`
    - `MobEffect#applyEffectTick`、`applyInstantenousEffect`、`onMobRemoved`、`onMobHurt` 现在接受 `ServerLevel`
    - `MobEffectInstance#onMobRemoved`、`onMobHurt` 现在接受 `ServerLevel`
- `net.minecraft.world.entity`
    - `AgeableMob$AgeableMobGroupData` 现在有一个公共构造函数
    - `AnimationState#getAccumulatedTime` -> `getTimeInMillis`
    - `Entity` 不再实现 `CommandSource`
        - `setOnGroundWithMovement` 现在接受一个额外的 `boolean` 表示是否有任何水平碰撞。
        - `getInputVector` 现在是 protected
        - `isAlliedTo(Entity)` -> `considersEntityAsAlly`
        - `teleportTo` 现在接受一个额外的 `boolean`，决定是否应设置相机
        - `checkInsideBlocks()` -> `recordMovementThroughBlocks`，不是一对一，因为它接受移动向量
        - `checkInsideBlocks(Set<BlockState>)` -> `collectBlockCollidedWith`，现在是私有的
        - `kill` 现在接受 `ServerLevel`
        - `hurt` 已被标记为已弃用，将被 `hurtServer` 和 `hurtClient` 取代
            - `hurtOrSimulate` 作为一个辅助方法，决定调用哪一个，也被标记为已弃用
        - `spawnAtLocation` 现在接受 `ServerLevel`
        - `isInvulnerableTo` -> `isInvulnerableToBase`，现在是 protected 和 final
            - `isInvulnerableTo` 已移至 `LivingEntity#isInvulnerableTo`
        - `teleportSetPosition` 现在是公开的，接受 `PositionMoveRotation` 和 `Relative` 集而不是 `DimensionTransition`
        - `createCommandSourceStack` -> `createCommandSourceStackForNameResolution`，不是一对一，因为它接受 `ServerLevel`
        - `mayInteract` 现在接受 `ServerLevel` 而不是仅仅 `Level`
        - `setOldRot` 现在是公开的
        - `changeDimension` -> `teleport`，给定 `TeleportTransition` 返回 `ServerPlayer`
        - `canChangeDimensions` -> `canTeleport`
    - `EntitySpawnReason#SPAWN_EGG` -> `SPAWN_ITEM_USE`，不是一对一，因为这表示实体可以从任何物品生成
    - `EntityType`
        - `create`、`loadEntityRecursive`、`loadEntitiesRecursive`、`loadStaticEntity` 现在接受一个 `EntitySpawnReason`
        - `*StackConfig` 现在接受一个 `Level` 而不是 `ServerLevel`
    - `EquipmentTable` 现在有一个构造函数，接受一个单一的 `float` 表示所有装备槽位的槽位掉落几率
    - `MobSpawnType` -> `EntitySpawnReason`
    - `Leashable#tickLeash` 现在接受 `ServerLevel`
    - `LivingEntity`
        - `getScale` 现在是 final
        - `onAttributeUpdated` 现在是 protected
        - `activeLocationDependentEnchantments` 现在接受一个 `EquipmentSlot`
        - `handleRelativeFrictionAndCalculateMovement` 现在是私有的
        - `updateFallFlying` 现在是 protected
        - `onEffectRemoved` -> `onEffectsRemoved`
        - `spawnItemParticles` 现在是公开的
        - `getLootTable` -> `Entity#getLootTable`，包装在 optional 中
        - `getBaseExperienceReward` 现在接受 `ServerLevel`
        - `triggerOnDeathMobEffects` 现在接受 `ServerLevel`
        - `canAttack` 已移除
        - `dropEquipment` 现在接受 `ServerLevel`
        - `dropExperience` 现在接受 `ServerLevel`
        - `dropFromLootTable` 现在接受 `ServerLevel`
        - `actuallyHurt`、`doHurtTarget` 现在接受 `ServerLevel`
        - `hasLineOfSight` 重载，带有剪辑上下文和眼睛 Y 提供者
        - `makePoofParticles` 现在是公开的
    - `Mob`
        - `pickUpItem`、`wantsToPickUp` 现在接受 `ServerLevel`
        - `equipItemIfPossible` 现在接受 `ServerLevel`
        - `customServerAiStep` 现在接受 `ServerLevel`
        - `dropPreservedEquipment` 现在接受 `ServerLevel`
    - `NeutralMob`
        - `isAngryAt`、`isAngryAtAllPlayers` 现在接受 `ServerLevel`
        - `playerDied` 现在接受 `ServerLevel`
    - `PortalProcessor#getPortalDestination` 现在返回一个 `TeleportTransition`
    - `PositionMoveRotation`
        - `of(ClientboundPlayerPositionPacket)` -> `ofEntityUsingLerpTarget(Entity)`
        - `of(DimensionTransition)` -> `of(TeleportTransition)`
    - `Shearable#shear` 现在接受 `ServerLevel` 和正在剪毛的 `ItemStack`
    - `RelativeMovement` -> `Relative`，扩展为包含增量移动
    - `WalkAnimationState#update` 现在接受一个额外的 `float` 表示移动时的位置缩放。
- `net.minecraft.world.entity.ai.behavior`
    - `StartAttacking` 现在接受一个 `$TargetFinder` 和一个 `$StartAttackingCondition`
        - 两者都是函数式接口，取代了之前的函数/谓词，但多了一个 `ServerLevel` 参数
    - `StopAttackingIfTargetInvalid` 现在接受一个 `$TargetErasedCallback` 和/或一个 `$StopAttackCondition`
        - 两者都是函数式接口，取代了之前的消费者/谓词，但多了一个 `ServerLevel` 参数
    - `MeleeAttack#create` 现在可以接受一个谓词来测试生物
    - `Swim` 现在接受一个代表生物的泛型
- `net.minecraft.world.entity.ai.control.LookControl#rotateTowards` -> `Control#rotateTowards`
- `net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal` 现在接受一个 `$Selector`
     - 这是一个函数式接口，取代了之前的谓词，但多了一个 `ServerLevel` 参数
- `net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.ai.sensing`
    - `NearestLivingEntitySensor`
        - `radiusXZ`、`radiusY` -> `Attributes#FOLLOW_RANGE`
        - `isMatchingEntity` 现在接受一个 `ServerLevel`
    - `Sensor`
        - `TARGETING_RANGE` 现在是私有的
        - `isEntityTargetable`、`isEntityAttackable`、`isEntityAttackableIgnoringLineOfSight` 现在接受一个 `ServerLevel`
        - `wasEntityAttackableLastNTicks`、`rememberPositives` 现在处理 `BiPredicate` 而不是 `Predicate`
- `net.minecraft.world.entity.ai.targeting.TargetingConditions`
    - `selector` 现在接受一个 `$Selector`
        - 这是一个函数式接口，取代了之前的谓词，但多了一个 `ServerLevel` 参数
    - `test` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.ai.village.poi.PoiRecord#codec`、`PoiSection#codec` -> `$Packed#CODEC`
- `net.minecraft.world.entity.animal`
    - `Fox$Type` -> `$Variant`
    - `MushroomCow$MushroomType` -> `$Variant`
        - `$Variant` 不再接受战利品表
    - `Salmon` 现在有一个表示其大小的变体
    - `Wolf`
        - `getBodyRollAngle` -> `#getShakeAnim`，不是一对一，因为角度是在渲染状态下计算的
        - `hasArmor` 已移除
- `net.minecraft.world.entity.animal.horse.AbstractHorse#followMommy` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.boss.enderdragon.EnderDragon#onCrystalDestroyed` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance#doServerTick` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.boss.wither.WitherBoss#getHead*Rot` -> `getHead*Rots`，返回所有旋转而不是仅返回提供的索引
- `net.minecraft.world.entity.decoration`
    - `ArmorStand` 默认旋转现在是公开的
        - `isShowArms` -> `showArms`
        - `isNoBasePlate` -> `showBasePlate`
    - `PaintingVariant` 现在接受一个标题和作者 `Component`
- `net.minecraft.world.entity.item.ItemEntity#getSpin` 现在是静态的
- `net.minecraft.world.entity.monster.Monster#isPreventingPlayerRest` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.monster.breeze.Breeze#getSnoutYPosition` -> `getFiringYPosition`
- `net.minecraft.world.entity.monster.hoglin.HoglinBase#hurtAndThrowTarget` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.monster.piglin.PiglinAi#isWearingGold` -> `#isWearingSafeArmor`
- `net.minecraft.world.entity.npc.InventoryCarrier#pickUpItem` 现在接受一个 `ServerLevel`
- `net.minecraft.world.entity.player`
    - `Player#disableShield` 现在接受要应用冷却时间的堆栈
    - `Inventory`
        - `findSlotMatchingUnusedItem` -> `findSlotMatchingCraftingIngredient`
        - `swapPaint` -> `setSelectedHotbarSlot`
        - `StackedContents` -> `StackedItemContents`
- `net.minecraft.world.entity.projectile`
    - `AbstractArrow#inGround` -> `IN_GROUND`，现在是一个 `EntityDataAccessor`
        - 可通过 `isInGround` 和 `setInGround` 受保护访问
    - `ThrowableItemProjectile` 现在可以接受一个被投掷物品的 `ItemStack`
- `net.minecraft.world.entity.raid.Raid#getLeaderBannerInstance` -> `getOminousBannerInstance`
- `net.minecraft.world.entity.vehicle`
    - `Boat$Type` 现在接受提供的船物品和物品的翻译键，但不再接受它们由什么木板制成
    - `ContainerEntity`
        - `*LootTable*` -> `ContainerLootTable`
        - `chestVehicleDestroyed` 现在接受一个 `ServerLevel`
    - `VehicleEntity`
        - `destroy` 现在接受一个 `ServerLevel`
        - `getDropItem` 现在是 protected
- `net.minecraft.world.item`
    - `BoatItem` 现在接受一个 `EntityType` 而不是变体和是否有箱子的布尔值
    - `ItemStack#hurtEnemy`、`postHurtEnemy` 现在接受一个 `LivingEntity` 而不是 `Player`
    - `SmithingTemplateItem` 现在接受 `Item.Properties` 而不是硬编码，对于静态初始化器也是如此
    - `UseAnim` -> `ItemUseAnimation`
- `net.minecraft.world.item.crafting.ShulkerBoxColoring` -> `TransmuteRecipe`，扩展为将存储在物品上的任何数据复制到结果物品
- `net.minecraft.world.item.enchantment.EnchantmentHelper`
    - `onProjectileSpawned` 现在接受一个 `Projectile` 而不是 `AbstractArrow`
- `net.minecraft.world.item.enchantment.effects.DamageItem` -> `ChangeItemDamage`
- `net.minecraft.world.level`
    - `GameRules` 在任何类型的构造期间都接受一个 `FeatureFlagSet`
        - `$IntegerValue#create` 接受一个 `FeatureFlagSet`
        - `$Type` 接受一个 `FeatureFlagSet`
    - `Level`
        - `setSpawnSettings` 不再接受一个 `boolean` 来决定是否生成友好生物
        - `getGameRules` -> `ServerLevel#getGameRules`
    - `LevelAccessor` 现在实现 `ScheduledTickAccess`，一个现在包含原本在 `LevelAccessor` 上的Tick调度方法的接口
        - `neighborShapeChanged` 交换了 `BlockState` 和邻居 `BlockPos` 参数的顺序
    - `LevelHeightAccessor`
        - `getMinBuildHeight` -> `getMinY`
        - `getMaxBuildHeight` -> `getMaxY`，该值比之前版本少一
        - `getMinSection` -> `getMinSectionY`
        - `getMaxSection` -> `getMaxSectionY`，该值比之前版本少一
    - `NaturalSpawner#spawnForChunk` 已被拆分为两个方法：`getFilteredSpawningCategories` 和 `spawnForChunk`
- `net.minecraft.world.level.biome#Biome#getPrecipitationAt`、`coldEnoughToSnow`、`warmEnoughToRain`、`shouldMeltFrozenOceanIcebergSlightly` 现在接受一个 `int` 表示生物群系的基础高度
- `net.minecraft.world.level.block`
    - `Block`
        - `shouldRenderFace` 接受正在检查的面的相对状态，不再传入 `BlockGetter` 或 `BlockPos`。
        - `updateEntityAfterFallOn` -> `updateEntityMovementAfterFallOn`
        - `$BlockStatePairKey` -> `FlowingFluid$BlockStatePairKey`，现在是包私有的
        - `getDescriptionId` -> `BlockBehaviour#getDescriptionId`，也是一个 protected 字段 `descriptionId`
    - `ChestBlock` 构造函数交换了参数顺序
    - `Portal#getPortalDestination` 现在返回 `TeleportTransition`
- `net.minecraft.world.level.block.entity`
    - `AbstractFurnaceBlockEntity#serverTick` 现在接受一个 `ServerLevel` 而不是 `Level`
    - `BrushableBlockEntity`
        - `brush` 现在接受等级和执行刷洗行为的堆栈
        - `unpackLootTable` 现在是私有的
        - `checkReset` 现在接受服务器等级
- `net.minecraft.world.level.block.state`
    - `BlockBehaviour`
        - `getOcclusionShape`、`getLightBlock`、`propagatesSkylightDown` 只接受 `BlockState`，不接受 `BlockGetter` 或 `BlockPos`
        - `getLootTable` 现在返回一个 `Optional`，也是一个 protected 字段 `drops`
        - `$BlockStateBase#getOcclusionShape`、`getLightBlock`、`getFaceOcclusionShape`、`propagatesSkylightDown`、`isSolidRender` 不再接受 `BlockGetter` 或 `BlockPos`
        - `$BlockStateBase#getOffset` 不再接受 `BlockGetter`
        - `$OffsetFunction#evaluate` 不再接受 `BlockGetter`
        - `$Properties#dropsLike` -> `overrideLootTable`
    - `StateHolder#findNextInCollection` 现在接受一个 `List` 而不是 `Collection`
- `net.minecraft.world.level.chunk`
    - `ChunkAccess`
        - `addPackedPostProcess` 现在接受一个 `ShortList` 而不是一个 `short`
        - `getTicksForSerialization` 现在接受一个 `long` 表示游戏时间
        - `unsaved` 现在是私有的
        - `setUnsaved` -> `markUnsaved`、`tryMarkSaved`
        - `$TicksToSave` -> `$PackedTicks`
    - `ChunkSource#setSpawnSettings` 不再接受一个 `boolean` 来决定是否生成友好生物
    - `LevelChunk#postProcessGeneration` 现在接受一个 `ServerLevel`
    - `Palette#copy` 现在接受一个 `PaletteResize`
- `net.minecraft.world.level.chunk.status.WorldGenContext` 现在接受一个 `Executor` 或主线程，而不是一个处理器句柄邮箱
    - 构造函数还接受一个 `LevelChunk$UnsavedListener`，用于当区块被标记为脏时
- `net.minecraft.world.level.chunk.storage`
    - `ChunkSerializer` -> `SerializableChunkData`
    - `ChunkStorage#write` 现在接受一个提供的 `CompoundTag` 而不是实例本身
    - `SectionStorage` 现在接受第二个泛型，表示存储数据的打包形式
        - 构造函数现在接受打包编解码器、一个将存储转换为打包格式的函数，以及一个将打包数据和脏 runnable 转换回存储的函数。
- `net.minecraft.world.level.levelgen`
    - `Aquifer$FluidStatus` 现在是一个记录
    - `WorldDimensions#withOverworld` 现在接受一个 `HolderLookup` 而不是 `Registry` 本身
    - `BlendingData` 现在有一个打包和解包状态，用于将内部数据序列化为一个简单对象
- `net.minecraft.world.level.levelgen.material.MaterialRuleList` 现在接受一个数组而不是一个列表
- `net.minecraft.world.level.levelgen.placement.PlacementContext#getMinBuildHeight` -> `getMinY`
- `net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement#getShuffledJigsawBlocks` 现在返回 `StructureTemplate$JigsawBlockInfo`
- `net.minecraft.world.level.lighting`
    - `LevelLightEngine#lightOnInSection` -> `lightOnInColumn`
    - `LightEngine`
        - `hasDifferentLightProperties`、`getOcclusionShape` 不再接受 `BlockGetter` 或 `BlockPos`
        - `getOpacity` 不再接受 `BlockPos`
        - `shapeOccludes` 不再接受两个 `long` 表示打包的位置
- `net.minecraft.world.level.material`
    - `FlowingFluid`
        - `spread` 现在接受当前位置的 `BlockState`
        - `getSlopeDistance` 之前的参数已被合并到一个 `$SpreadContext` 对象中
        - `spread`、`getNewLiquid`、`canConvertToSource`、`getSpread` 现在接受一个 `ServerLevel`
    - `Fluid`
        - `tick` 现在接受当前位置的 `BlockState`
        - `tick` 和 `randomTick` 现在接受 `ServerLevel`
    - `FluidState`
        - `tick` 现在接受当前位置的 `BlockState`
        - `tick` 和 `randomTick` 现在接受 `ServerLevel`
    - `MapColor#calculateRGBColor` -> `calculateARGBColor`
- `net.minecraft.world.level.portal`
    - `DimensionTransition` -> `TeleportTransition`
        - `pos` -> `position`
        - `speed` -> `deltaMovement`
        - 构造函数现在可以接受一组 `Relatives` 来指示位置应相对于另一个位置移动的哪些运动
    - `PortalShape#createPortalBlocks` 现在接受一个 `LevelAccessor`
- `net.minecraft.world.level.saveddata.SavedData#save(File, HolderLookup$Provider)` 现在返回 `CompoundTag`，不在方法中将数据写入文件
- `net.minecraft.world.level.storage`
    - `DimensionDataStorage` 现在实现 `AutoCloseable`
        - 构造函数接受一个 `Path` 而不是 `File`
        - `save` -> `scheduleSave` 和 `saveAndJoin`
    - `LevelData#getGameRules` -> `ServerLevelData#getGameRules`
- `net.minecraft.world.phys.BlockHitResult` 现在接受一个布尔值表示是否击中了世界边界
    - 添加了两个辅助方法 `hitBorder`、`isWorldBorderHit`
- `net.minecraft.world.ticks`
    - `ProtoChunkTicks#load` 现在接受一个保存的Tick列表
    - `SavedTick#loadTickList` 现在返回一个保存的Tick列表，而不是消费它们
    - `SerializableTickContainer#save` -> `pack`

### 移除列表

- `com.mojang.blaze3d.Blaze3D`
    - `process`
    - `render`
- `com.mojang.blaze3d.pipeline.RenderPipeline`
    - 被 `com.mojang.blaze3d.framegraph.*` 和 `com.mojang.blaze3d.resources.*` 取代
- `com.mojang.blaze3d.platform.NativeImage`
    - `setPixelLuminance`
    - `getRedOrLuminance`、`getGreenOrLuminance`、`getBlueOrLuminance`
    - `blendPixel`
    - `asByteArray`
- `com.mojang.blaze3d.systems.RenderSystem`
    - `glGenBuffers`
    - `glGenVertexArrays`
    - `_setShaderTexture`
    - `applyModelViewMatrix`
- `net.minecraft.Util#wrapThreadWithTaskName(String, Supplier)`
- `net.minecraft.advancements.critereon.EntitySubPredicates#BOAT`
- `net.minecraft.client.Options#setKey`
- `net.minecraft.client.gui.screens.inventory.EnchantmentScreen#time`
- `net.minecraft.client.multiplayer`
    - `ClientCommonPacketListenerImpl#strictErrorHandling`
    - `ClientLevel#isLightUpdateQueueEmpty`
    - `CommonListenerCookie#strictErrorHandling`
- `net.minecraft.client.particle.ParticleRenderType#PARTICLE_SHEET_LIT`
- `net.minecraft.client.renderer`
    - `GameRenderer#resetProjectionMatrix`
    - `LevelRenderer`
        - `playJukeboxSong`
        - `clear`
    - `PostChain`
        - `getTempTarget`、`addTempTarget`
    - `PostPass`
        - `setOrthoMatrix`
        - `getFilterMode`
- `net.minecraft.client.renderer.block.model.BlockModel#fromString`
- `net.minecraft.client.renderer.texture`
    - `AbstractTexture#blur`、`mipmap`
    - `TextureManager#bindForSetup`
- `net.minecraft.commands.arguments.coordinates.WorldCoordinates#current`
- `net.minecraft.core`
    - `Direction#fromDelta`
    - `Registry#getOrCreateTag`、`getTagNames`、`resetTags`
- `net.minecraft.server.MinecraftServer`
    - `isSpawningAnimals`
    - `areNpcsEnabled`
- `net.minecraft.server.level`
    - `GenerationChunkHolder#getGenerationRefCount`
    - `ServerPlayer`
        - `setPlayerInput`
        - `teleportTo(ServerLevel, double, double, double, float, float, boolean)`
- `net.minecraft.tags`
    - `TagManager`
    - `TagManagerSerialization$TagOutput`
- `net.minecraft.world.entity`
    - `AnimationState#updateTime`
    - `Entity`
        - `walkDist0`、`walkDist`
        - `wasOnFire`
        - `tryCheckInsideBlocks`
    - `EntitySelector$MobCanWearArmorEntitySelector`
- `net.minecraft.world.entity.ai.sensing`
    - `BreezeAttackEntitySensor#BREEZE_SENSOR_RADIUS`
    - `TemptingSensor#TEMPTATION_RANGE`
- `net.minecraft.world.entity.animal`
    - `Cat#getTextureId`
    - `Squid#setMovementVector`
    - `Wolf#isWet`
- `net.minecraft.world.entity.boss.dragon.EnderDragon`
    - `getLatencyPos`
    - `getHeadPartYOffset`
- `net.minecraft.world.entity.monster.Zombie#supportsBreakDoorGoal`
- `net.minecraft.world.entity.npc.Villager#setChasing`、`isChasing`
- `net.minecraft.world.entity.projectile`
    - `AbstractArrow#shotFromCrossbow`
    - `ThrowableProjectile(EntityType, LivingEntity, Level)`
- `net.minecraft.world.item`
    - `BannerPatternItem#getDisplayName`
    - `ItemStack#LIST_STREAM_CODEC`
- `net.minecraft.world.level.BlockGetter#getMaxLightLevel`
- `net.minecraft.world.level.block.entity.JigsawBlockEntity$JointType#byName`
- `net.minecraft.world.level.block.state.BlockBehaviour#isOcclusionShapeFullBlock`
- `net.minecraft.world.level.chunk.ChunkAccess#setBlendingData`
- `net.minecraft.world.level.storage.loot.LootDataType#deserialize`
- `net.minecraft.world.phys.AABB#getBottomCenter`
- `net.minecraft.world.phys.shapes.Shapes#getFaceShape`
- `net.minecraft.world.ticks.SavedTick#saveTick`
