Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

1.21.1 到 26.1 NeoForge 移植指南

  • 原始仓库:https://github.com/Leclowndu93150/Porting-Primers
  • 原始地址:https://leclowndu93150.github.io/Porting-Primers

本网站索引了上游 NeoForge 移植入门文档,以便您直接跳转到相关章节。

这里涵盖的上游链条是:

1.21.1 -> 1.21.2/3 -> 1.21.4 -> 1.21.5 -> 1.21.6 -> 1.21.7 -> 1.21.8 -> 1.21.9 -> 1.21.10 -> 1.21.11 -> 26.1

上游没有单独的 1.21.3 入门文档。1.21.2 的入门文档涵盖了 1.21.1 -> 1.21.2/3 这一步。

如何使用本网站

如果您知道哪个子系统发生了变化,请使用下面的主题地图。每个链接都直接指向相关章节。

如果同一子系统在多个版本中都发生了变化,请参阅频繁变更的系统了解阅读顺序。

如果您想要原始的入门文档,请参阅详细入门文档,其中包含指向每个章节的锚点链接的完整目录。

如果您遇到编译错误,请使用类和方法的索引来查找它在哪里发生了变化。


主题地图

构建、映射、名称、导入和包移动

数据生成、资源包、注册表、标签、编解码器、战利品、验证和配方序列化

物品、组件、装备、盔甲、工具、战斗、染料和消耗品

渲染、模型、着色器、粒子、方块模型、物品模型、材质、纹理图集和视觉管线

实体、生物、生物 AI、转化、生成和实体数据

GUI、输入、按键绑定、调试屏幕、调试工具、RPC 工具和测试基础设施

世界状态、保存数据、游戏规则、时间线、时钟、玩家、权限、路径点和其他服务端系统

其余的小幅迁移

每份入门文档的“小幅迁移”章节中还包含“新标签”、“标签变更”、“新增列表”、“变更列表”和“移除列表”子章节。如需查看这些内容,请前往详细入门文档中的完整入门文档页面。


类和方法索引

如果您遇到编译错误或需要查找特定类/方法在哪里发生了变化,请在此表中搜索。

类 / 方法版本章节
AbstractFurnaceBlockEntity 燃料1.21.2燃料值
AbstractMinecart1.21.2矿车行为
Activities / Brain26.1活动与大脑
AnimationDefinition#bake1.21.6动画烘焙
ArmorItem / ArmorMaterial1.21.2盔甲材料、装备和模型(纹理)
BakedModel / BakedQuad1.21.5模型重做
BlockBehaviour#neighborChanged1.21.2朝向
BlockEntityType 构造器1.21.2BlockEntityTypes 私有化了!
CauldronInteraction26.1炼药锅交互调度器
ChunkPos (现为记录)26.1ChunkPos,现在是一个记录
ChunkSectionLayer1.21.6ChunkSectionLayers
客户端物品 JSON1.21.4客户端物品
Consumable / ConsumableListener1.21.2消耗品
DataComponents 获取器1.21.5数据组件获取器
DataComponents 新类型1.21.11新数据组件
DataComponents 初始化器26.1数据组件初始化器
DiggerItem / SwordItem 移除1.21.5武器、工具和盔甲:去除冗余
DyeRecipe / DyeItem26.1染料组件
Entity#interactAt 移除26.1interactAt 的移除
EntityReference (取代 UUID)1.21.5实体引用
EntityRenderState1.21.2实体渲染状态
Explosion (现为接口)1.21.2爆——炸——!
GameRules1.21.11游戏规则洗牌
GameTest 框架1.21.5游戏测试大修
GenerationStep$Carving 移除1.21.2移除雕刻生成步骤
GpuTexture / RenderPipeline1.21.5渲染管线重做
GuiGraphics / GUI 渲染1.21.6GUI 变更
Holder / HolderSet / HolderGetter1.21.2持有者集过渡
Identifier (原 ResourceLocation)1.21.11ResourceLocation 到 Identifier
Ingredient1.21.2原料的转变
InteractionResult1.21.2交互结果
ItemInstance / StackTemplate26.1物品实例与堆栈模板
KeyMapping / 输入事件1.21.9输入处理整合
Leashable1.21.6拴绳
Level#isClientSide1.21.9Level#isClientSide 现在为 private
Level#random26.1Level#random 字段现在为 protected
LootContextParam / LootContextParamSet1.21.2上下文键
LootPoolEntry / 战利品编解码器26.1战利品类型展开
Mob#convertTo1.21.2生物转化
OptionEnum 移除1.21.11OptionEnum 移除
Permission / PermissionSet1.21.11权限大修
Profiler#get (取代 getProfiler)1.21.2分析器与 Tracy 客户端
Recipe 注册表格式1.21.2配方,现在采用注册表格式
RecipeDisplay / SlotDisplay1.21.2配方,现在采用注册表格式
RenderType 洗牌1.21.11哦,又来了,一次渲染重写
SavedData / SavedDataType1.21.5保存数据,现在带有类型
ServerExplosion1.21.2爆——炸——!
着色器 JSON / .vsh / .fsh1.21.2着色器重写
SimpleJsonResourceReloadListener1.21.4SimpleJsonResourceReloadListener
TagProvider 追加器1.21.6标签提供者:追加器重写
Validatable / ValidationContext26.1验证大修
村民交易(数据包)26.1数据包村民交易
VoxelShape 辅助类1.21.5体素形状辅助类
Waypoint 系统1.21.6路径点
世界时钟 / 时间标记26.1世界时钟与时间标记
世界数据拆分26.1将主关卡数据拆分为保存数据

来源与署名

拆分后的入门文档页面复制自 ChampionAsh5357/neoforged-github,分支 update/26.1。详见来源与署名

频繁变更的系统

此页面是直接移植的防护栏。

当同一子系统在多个中间版本中发生变化时,不要将最早的迁移说明视为最终版本。请使用最新的适用版本作为真实来源,但仍需先应用旧章节的内容,这样才能使中间的 API 过渡看起来合理。

渲染与图形

相关章节:

如何阅读它们:

  • 1.21.2/3 修改了 GUI 贴图混合、着色器 JSON 结构以及渲染状态假设。
  • 1.21.5 是第一次大型渲染基础设施重写,围绕 RenderPipelineGpuTexture 和渲染通道展开。
  • 1.21.6 通过准备/渲染状态分离再次修改了 GUI 渲染流程。
  • 1.21.9 修改了功能提交到渲染的方式。
  • 1.21.11 修改了采样器、渲染类型、地形拆分和纹理图集。
  • 26.1 是方块/物品渲染、材质、染色源、流体模型、粒子层以及面向后端的渲染 API 的最终权威。

实用规则:

  • 26.1 视为最终的渲染目标。
  • 保留 1.21.4 客户端物品和 1.21.6 GUI 流程作为仍然有效的要求,而不是过时的历史。

物品模型与物品元数据

相关章节:

哪些内容留存下来:

  • 1.21.4 客户端物品是物品渲染数据的基线。
  • 1.21.5 移除了更多硬编码的物品类假设,改用组件和装备数据。
  • 1.21.91.21.1126.1 进一步改变了物品参与渲染和元数据管道的方式。

实用规则:

  • 首先将物品资源转换为客户端物品。
  • 然后围绕组件移植行为和元数据。
  • 最后对照 26.1 的渲染和物品实例模型进行验证。

标签、注册表、编解码器与验证

相关章节:

哪些内容留存下来:

  • 1.21.2/3HolderHolderSet 开始影响代码库大部分内容的版本。
  • 1.21.5 修改了标签访问、解析器行为、基于编解码器的读写以及保存数据的构造。
  • 1.21.6 修改了标签提供者的构建方式,并推动更多代码转向通用编码和解码。
  • 1.21.11 带来了重命名的变动,影响注册表和标识符相关的代码。
  • 26.1 通过战利品类型展开和验证大修最终确定了更多基于编解码器的基础设施。

实用规则:

  • 前面的章节告诉您如何迁移到基于持有者和编解码器的 API。
  • 26.1 是验证和战利品注册形式的最终目标。

数据组件

相关章节:

哪些内容留存下来:

  • 1.21.2/3 引入了重要的组件相关迁移,例如消耗品和配方相关数据的移动。
  • 1.21.5 扩展了以组件为中心的工具、盔甲、武器以及通用数据访问行为。
  • 1.21.11 添加了更多组件类型。
  • 26.1 继续添加初始化器、染料组件以及更多组件。

实用规则:

  • 随着版本推进,物品和配方将越来越少地由类驱动,而越来越多地由组件驱动。

保存数据与世界状态

相关章节:

哪些内容留存下来:

  • 1.21.5 将保存数据迁移到 SavedDataType
  • 26.1 进一步将主关卡数据拆分到专用的保存数据对象中。

实用规则:

  • 先完成 1.21.5 的迁移,然后在 26.1 中重新审视每个关卡/世界持久化的假设。

开发者工具、测试、调试与权限

相关章节:

哪些内容留存下来:

  • 1.21.5 大修了游戏测试。
  • 1.21.9 大修了调试和管理服务器的形态。
  • 1.21.11 添加了权限大修和以 gizmo 为中心的可视化工作。
  • 26.1 添加了 Java 25 以及更多面向工具的小改动。

实用规则:

  • 先移植游戏玩法代码。
  • 然后根据后续章节重新启用您的调试、测试和仅限操作员的工具。

详细入门文档

这些章节按步骤保留了上游入门文档的内容。每个章节标题都直接链接到入门文档页面内的相应章节。

1.21.1 -> 1.21.2/3

完整入门文档

1.21.2/3 -> 1.21.4

完整入门文档

1.21.4 -> 1.21.5

完整入门文档

1.21.5 -> 1.21.6

完整入门文档

1.21.6 -> 1.21.7

完整入门文档

1.21.7 -> 1.21.8

完整入门文档

1.21.8 -> 1.21.9

完整入门文档

1.21.9 -> 1.21.10

完整入门文档

1.21.10 -> 1.21.11

完整入门文档

1.21.11 -> 26.1

完整入门文档

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

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

持有者集 过渡

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

JSON 示例:

// HolderSet#direct 包含一个元素
{
    "holder_set": "minecraft:apple"
}

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

// HolderSet 引用(标签)
{
    "holder_set": "#minecraft:planks"
}

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

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

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

// 物品的直接 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

// 物品的命名 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 的大小。

// 对于某个 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 已移除 - 现在是 blitblitSprite 方法中的一个参数
    • 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 现在接受一个布尔值,表示纹理的中心部分是否应拉伸以适应大小。

着色器重写

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

着色器文件

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

DiffuseSamplerDiffuseDepthSampler 已根据应用目标被赋予新名称:InSamplerMainSamplerMainDepthSamplerInSampler 用于除 transparency 程序着色器之外的所有场景。

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

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

// 旧的后处理效果着色器 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 头。

// 对于某个 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 ] }
    ]
}
// 对于某个 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() {
    // 在此处设置输出值
}
// 对于某个 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() {
    // 在此处设置输出值
}

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

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

// 访问 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 引用。

// 在某个渲染方法中
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
    • BlendModeEffectEffectProgramProgramProgramManagerShader 已被整合到 CompiledShader
    • Unform 不再接受 Shader
      • glGetAttribLocation 已移除
      • glBindAttribLocation -> VertexFormat#bindAttributes
      • setFromConfig - 根据另一个统一配置的值和计数设置统一参数。
  • com.mojang.blaze3d.systems.RenderSystem
    • setShader 现在接受 CompiledShaderProgramShaderProgram
    • clearShader - 清除当前系统着色器。
    • runAsFancy 已移除,由 LevelRenderer#getTransparencyChain 内部处理
    • setProjectionMatrix 现在接受一个 ProjectionType 而不仅仅是 VertexSorting
    • getVertexSorting -> getProjectionType;不是一对一,但 VertexSorting 可在 ProjectionType 上访问
  • com.mojang.blaze3d.vertex.VertexBuffer
    • drawWithShader 在传入 nullCompiledShaderProgram 时将成为空操作
    • $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 而不是输入和输出 RenderTargetboolean 过滤模式,要使用的 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
      • entityTranslucentCullentityGlintDirect 已移除
      • 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。这些字段应该是可变的,因为状态类只为每个渲染器创建一次。

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

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

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,获取根 ModelPartallParts,返回所有 ModelPart 的扁平列表;以及 resetPose,将 ModelPart 恢复到其默认状态。

LayerDefinitionMeshDefinitionPartDefinitionCubeDeformationLayerDefinitionsModelLayerLocation -> LayerDefinition 映射的实现和构造保持不变。

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

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,不过这次它接受渲染状态而不是实体。需要实现/覆盖的新方法是 createRenderStateextractRenderStatecreateRenderState 构造默认渲染状态对象。而 extractRenderState 则填充当前正在渲染的实体的渲染状态。如果您没有使用现有的渲染状态类,则需要覆盖 extractRenderState

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

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_paddleright_paddle,并根据船的划桨时间进行动画。
    • AgeableHierarchicalModelColorableAgeableListModelAgeableListModel -> BabyModelTransform
    • AnimationUtils
      • animateCrossbowCharge 现在接受一个表示充能持续时间的 float 和一个表示使用刻数的 int,而不是 LivingEntity
      • swingWeaponDown 现在接受一个 HumanoidArm 而不是 Mob
    • BabyModelTransform - 一种网格变换器,应用模型的幼年缩放形式。
    • BoatModel
      • createPartsBuilder 已移除
      • createChildren -> addCommonParts,现在是私有的
      • createBodyModel -> createBoatModelcreateChestBoatModel
      • waterPatch -> createWaterPatch
      • parts 已移除
    • ChestBoatModel -> BoatModel#createChestBoatModel
    • ChestedHorseModel 类已移除,现在完全存在于 LlamaModelDonkeyModel
    • 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#getTendrilsLayerModelPartsgetHeartLayerModelPartsgetBioluminescentLayerModelPartsgetPulsatingSpotsLayerModelParts 现在接受 WardenRenderState
    • WaterPatchModel -> BoatModel#createWaterPatchModel$Simple
  • net.minecraft.client.model.geom
    • ModelLayerLocation 现在是一个记录
    • ModelLayers
      • createRaftModelNamecreateChestRaftModelName 已移除
      • createSignModelName -> createStandingSignModelNamecreateWallSignModelName
      • createBoatModelNamecreateChestBoatModelName 已移除
    • ModelPart
      • rotateBy - 使用给定的 Quaternionf 旋转部件。
      • $Cube#polygons$Polygon$Vertex 现在是公开的
    • PartPose 现在是一个记录
      • translated - 平移一个姿势。
      • withScalescaled - 缩放一个姿势。
  • 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 现在接受渲染状态而不是实体
      • getAttackAnimgetBob 现在在渲染状态中
      • 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
    • renderRightHandrenderLeftHand 现在接受一个 ResourceLocation 而不是 AbstractClientPlayer,以及一个 boolean 表示是否渲染左袖和/或右袖
    • setupRotations 现在接受渲染状态而不是实体和参数信息
  • net.minecraft.world.entity
    • AnimationState#copyFrom - 从另一个状态复制动画状态。
    • Entity
      • noCulling -> EntityRenderer#affectedByCulling
      • getBoundingBoxForCulling -> EntityRenderer#getBoundingBoxForCulling
    • LerpingModel 类已移除
    • PowerableMob 类已移除

模型烘焙

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

// 对于某个 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#getDependenciesresolveParents -> resolveDependencies
    • BlockModelDefintion 现在接受一个 MultiPart$Definition,不存在接受 List<BlockModelDefinition> 的构造函数
      • fromStreamfromJsonElement 不再接受 $Context
      • getVariants 已移除
      • isMultiPart 已移除
      • instantiate -> MultiPart$Definition#instantiate
    • MultiVariant 现在是一个记录
    • UnbakedBlockStateModel - 一个表示方块状态模型的接口,包含一个将具有相同模型的状态分组在一起的单一方法。
    • VariantSelector - 用于从模型描述符构建状态定义的工具。
  • net.minecraft.client.renderer.block.model
    • BlockModel
      • MISSING_MATERIAL - 缺失方块纹理的材质。
      • bake 不再接受 ModelBakerBlockModel
      • $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 取代
    • SimpleBakedModelSimpleBakedModel$Builder 不再接受 ItemOverrides
    • SpecialModels - 内置模型的工具。
    • UnbakedModel
      • getDependenciesresolveParents -> resolveDependencies
      • bake 不再可为 null
      • $Resolver - 确定在顶层或覆盖时如何加载未烘焙模型。
    • WeightedBakedModel 现在接受一个 SimpleWeightedRandomList 而不是 WeightedEntry 的列表

装备与物品、模型等等

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

物品名称和模型

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

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

可附魔、可修复物品

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

鞘翅 -> 滑翔翼

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

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 中的属性。

// 某个工具材料
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)。

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 并只允许特定实体穿戴它们。

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

让我们深入一层。

数据组件

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

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

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

Equippable

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

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 是一个枚举,表示要渲染装备模型的层。虽然这些是非特定的,但它们由特定的实体渲染器通过层渲染器实现和读取。例如,HUMANOIDHumanoidArmorLayer 用于渲染头部、胸部和脚部;因此,任何对 HUMANOID 的使用都将使用该系统进行渲染。另一个例子是 WOLF_BODYWolfArmorLayer 用于渲染身体盔甲。因此,如果使用现有的层类型(除非您的模组加载器支持枚举扩展,否则这是唯一的情况),请确保它们与现有的渲染器兼容。

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

// 在 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
            }
            // ...
        ]
        // ...
    }
}
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();

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

// 在某个渲染方法中,其中 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#renderTooltiprenderComponentTooltip 现在有一个参数,用于接受工具提示背景和框架纹理的相对目录,如果为 null 则使用默认值
  • net.minecraft.client.gui.screens.inventory.tooltip.TooltipRenderUtil#renderTooltipBackground 现在有一个参数,用于接受工具提示背景和框架纹理的相对目录,如果为 null 则使用默认值
  • net.minecraft.client.renderer.block.model
    • ItemOverrides -> BakedOverrides
      • 构造函数不再接受父级 BlockModel
      • resolve -> findOverride,不再接受后备模型
    • ItemOverrideItemOverride$Predicate 现在是一个记录
      • getPredicates 已移除,使用 predicates
      • getModel -> model
  • net.minecraft.client.renderer.entity
    • EntityRenderDispatcher 现在接受 EquipmentModelSet
    • EntityRendererProvider$Context
      • getEquipmentModels - 获取当前装备纹理。
      • getEquipmentRenderer - 获取装备的渲染器。
    • ItemRenderer 不再接受 Minecraft 实例和 TextureManager
      • TRIDENT_MODELSPYGLASS_MODEL 现在是公开的
      • TRIDENT_IN_HAND_MODELSPYGLASS_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 现在是私有的,被一个只接受 HumanoidArmPlayerRenderState 的公共方法取代
  • 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
      • canTakeItemDataComponents#EQUIPPABLE 取代
      • canEquipWithDispenser - 返回堆栈在从发射器发射时是否可以装备。
      • canDispenserEquipIntoSlot - 一个实体覆盖,指定发射器是否可以将装备放入给定槽位。
      • isEquippableInSlot - 返回堆栈是否可以在给定槽位中装备。
      • canGlideUsing - 实体是否可以使用提供的槽位中的堆栈滑翔。
    • Mob
      • canReplaceCurrentItem 现在接受 EquipmentSlot
      • isBodyArmorItemDataComponents#EQUIPPABLE 取代
  • net.minecraft.world.entity.animal.horse
    • Horse#isBodyArmorItemDataComponents#EQUIPPABLE 取代
    • Llama#isBodyArmorItemgetSwagDataComponents#EQUIPPABLE 取代
  • net.minecraft.world.item
    • AnimalArmorItem 不再继承 ArmorItem
      • 构造函数不再接受一个表示覆盖纹理的布尔值,因为现在这是 EquipmentModel 的一部分
      • 构造函数可以接受一个可选的 Holder<SoundEvent> 作为装备声音
      • 构造函数可以接受一个 boolean 表示如果实体受伤,盔甲是否应该损坏
      • $BodyType 现在接受允许穿戴盔甲的实体,而不是指向纹理的路径工厂
    • ArmorItem 不再是可装备的
      • 基本上作为一个物品类,其剩余的唯一用途是在附魔时防止盔甲更换并获取关联的属性
      • $Type -> ArmorType
    • ArmorMaterial -> .equipment.ArmorMaterial
      • 基本上是一个虚拟记录,用于轻松处理应用关联的数据组件(MAX_DAMAGEATTRIBUTE_MODIFIERSENCHANTABLEEQUIPPABLEREPAIRABLE
    • ArmorMaterials -> .equipment.ArmorMaterials
    • BookItemEnchantedBookItem -> 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
      • isEnchantablegetEnchantmentValue 已移除
      • isValidRepairItem 已移除
      • getDefaultAttributeModifiers 已移除
      • getDamageSource - 返回此物品对 LivingEntity 造成的伤害来源
      • isComplex 已移除
      • $Properties
        • equippable - 设置一个可装备组件,定义物品如何装备
        • equippableUnswappable - 设置一个无法通过按键快捷方式交换的可装备组件。
        • overrideDescription - 设置物品的翻译键。
        • overrideModel - 设置模型资源位置。
      • getCraftingRemainingItemhasCraftingRemainingItem -> 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 实现结合了 InteractionResultHolderItemInteractionResult,因此所有用途也已被替换。

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

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

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

  • SUCCESS - 一个在客户端挥动手的 $Success 对象。
  • SUCCESS_SERVER - 一个在服务器端挥动手的 $Success 对象。
  • CONSUME - 一个不挥动手的 $Success 对象。
  • FAIL - 一个 $Fail 对象。
  • PASS - 一个 $Pass 对象。
  • TRY_WITH_EMPTY_HAND - 一个 $TryEmptyHandInteraction 对象。
// 对于某个返回 InteractionResult 的方法
return InteractionResult.PASS;

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

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

// 或者
return InteractionResult.SUCCESS.withoutItem();
  • net.minecraft.core.cauldron.CauldronInteraction
    • interact 现在返回一个 InteractionResult
    • fillBucketemptyBucket 现在返回一个 InteractionResult
  • net.minecraft.world
    • InteractionResultHolderItemInteractionResult -> InteractionResult
  • net.minecraft.world.item
    • Equipable#swapWithEquipmentSlot 现在返回一个 InteractionResult
    • Item#useItemStack#use 现在返回一个 InteractionResult
    • ItemUtils#startUsingInstantly 现在返回一个 InteractionResult
    • JukeboxPlayable#tryInsertIntoJukebox 现在返回一个 InteractionResult
  • net.minecraft.world.level.block.state.BlockBehaviour#useItemOn$BlockStateBase#useItemOn 现在返回一个 InteractionResult

乐器 数据包版

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

// 在 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"
    },
}
// 对于某个 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 中定义或通过数据生成生成。

// 在 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"
}
// 对于某个 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 现在接受 TrialSpawnerConfigHolder
      • canSpawnInLevel 现在接受一个 ServerLevel
    • TrialSpawnerConfig
      • CODEC -> DIRECT_CODEC
      • $Builderbuilder - 试炼刷怪笼配置的构建器

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

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

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 - 通过传入结果方块和基础方块的 BlockBlockFamily 创建配方。
      • $Runner - 一个 DataProvider,通过 createRecipeProvider 构造 RecipeProvider
    • ShapedRecipeBuilderShapelessRecipeBuilder 现在有私有构造函数,并接受物品的 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 已被移除,意味着只需要提供客户端构造函数和方块实体可以位于的有效方块集合。

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

消耗品

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

Consumable 数据组件

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

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

// 对于某个物品
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 并返回应播放的声音事件。

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

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

ConsumableListener

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

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

    // ...

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

ConsumeEffect

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

// 构造消耗品时
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 处理。只有当使用后堆栈为空时,剩余物才会被转换。否则,它将返回当前堆栈,只是使用了一个物品。

// 对于某个物品
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 注册表名称(如果未指定),要么引用一个自定义资源位置。应用冷却时间时,它将冷却实例存储在匹配定义组的任何东西上。这意味着,如果某个堆栈定义了冷却组,当使用普通物品时,它不会受到影响。

// 对于某个物品
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
    • getDrinkingSoundgetEatingSound 已移除,由 ConsumeEffect 处理
    • triggerItemUseEffects 已移除
    • eat 已移除
  • net.minecraft.world.entity.npc.WanderingTrader 现在实现 Consumable$OverrideConsumeSound
  • net.minecraft.world.food
    • net.minecraft.world.food.FoodData
      • tick 现在接受一个 ServerPlayer
      • getLastFoodLevelgetExhaustionLevelsetExhaustion 已移除
    • FoodProperties 现在是一个 ConsumableListener
      • eatDurationTickseatSeconds -> 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 现在接受 ItemStackResourceLocation 作为其方法的参数,而不仅仅是 Item
      • getCooldownGroup - 返回表示应用冷却时间的组的键
    • ItemStack#getDrinkingSoundgetEatingSound 已移除
    • 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。如果在传入之前未设置此值,将抛出错误。

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 可能被 RecipeDisplayIdRecipeDisplayRecipeDisplayEntry 取代,如果不需要 holder 本身的话。随之而来的是,配方书的处理方式也有一些变化。

配方书

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

// 假设某个 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
}

配方显示

但是,配方如何理解应在配方书中显示什么?这属于两个新的静态注册表:RecipeDisplaySlotDisplay

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

槽位还有通过 resolveForStacksresolveForFirstStack 获取可显示的相关堆栈的方法。

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 注册,该类型接受映射编解码器和流编解码器。

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 可以通过 IngredientList<Ingredient>List<Optional<Ingredient>> 使用 createcreateFromOptionals 分别创建。

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
      • getIngredientsisIncomplete -> placementInfo
        • getIngredients -> PlacementInfo#stackedRecipeContents
        • isIncomplete -> PlacementInfo#isImpossibleToPlace
    • RecipeManager#getSynchronizedRecipes - 返回所有可以放置的配方并将它们发送到客户端。没有其他配方被同步。
    • ShapedRecipePattern 现在接受一个 List<Optional<Ingredient>> 而不是 NonNullList<Ingredient>
    • ShapelessRecipe 现在接受一个 List<Ingredient> 而不是 NonNullList<Ingredient>
    • SmithingTransformRecipeSmithingTrimRecipe 现在接受 Optional<Ingredient> 而不是 Ingredient
    • SuspiciousStewRecipe 类已移除

配方变更

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

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 来完成的。

// 使用标准的原版注册表方法
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#recipeaddRecipe 现在接受一个 ResourceKey
  • net.minecraft.advancements.critereon
    • PlayerPredicate 现在接受一个 ResourceKey 作为配方映射
      • $Builder#addRecipe 现在接受一个 ResourceKey
    • RecipeCraftedTrigger
      • trigger 现在接受一个 ResourceKey
      • $TriggerInstance 现在接受一个 ResourceKey
      • $TriggerInstance#craftedItemcrafterCraftedItem 现在接受一个 ResourceKey
    • RecipeUnlockedTrigger
      • unlocked 现在接受一个 ResourceKey
      • $TriggerInstance 现在接受一个 ResourceKey
  • net.minecraft.client
    • ClientRecipeBook
      • setupCollections -> rebuildCollections,不是一对一
      • getCollection(RecipeBookCategories) -> getCollection(ExtendedRecipeBookCategory)
      • addremove - 处理在配方书中添加/移除要显示的配方条目。
      • addHighLightremoveHighlighthasHighlight - 处理当被玩家过滤或选择时条目是否高亮显示。
      • clear - 清除已知和高亮显示的配方。
    • RecipeBookCategories#*_MISC -> SearchRecipeBookCategory#*
      • 这也可以在方法中被 RecipeBookComponent$TabInfoExtendedRecipeBookCategoryRecipeBookCategory 取代
  • 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
    • AbstractFurnaceReipceBookComponentBlastingFurnaceReipceBookComponentSmeltingFurnaceReipceBookComponentSmokingFurnaceReipceBookComponent -> FurnaceReipceBookComponent
    • GhostRecipe -> GhostSlots,不是一对一,因为配方本身作为 RecipeHolder 存储在 RecipeBookComponent 的一个私有字段中
      • addResult -> setResult,不是一对一
      • addIngredient -> setIngredient,不是一对一
      • setSlotsetInputsetResult 现在接受一个 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
      • getRecipesgetDisplayRecipes -> getSelectedRecipes
      • registryAccesshasKnownRecipesupdateKnownRecipes 已移除
      • 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
      • addcontainsremove -> ServerRecipeBook#addcontainsremove
      • addHighlightremoveHighlightwillHighlight -> ServerRecipeBook#addHighlightremoveHighlightClientRecipeBook#hasHighlight
      • bookSettings 现在是 protected
    • RecipeBookSettings#readwrite 现在是私有的
    • 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#hasSlotgetInputSlotIndexes 已移除
    • 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 - 从配方注册表创建配方映射
      • logImpossibleRecipeshasErrorsLoading 已移除
      • getRecipeFor 现在接受一个 ResourceKey,之前是 ResourceLocation
      • getRecipesForgetAllRecipesFor -> RecipeMap#getRecipesFor
      • byType 已移除
      • getRemainingItemsFor 已移除
      • byKeybyKeyTyped 现在接受一个 ResourceKey
      • getOrderedRecipes 已移除
      • getSynchronizedRecipes -> getSynchronizedItemPropertiesgetSynchronizedStonecutterRecipes;不是一对一
      • getRecipeIds 已移除
      • getRecipeFromDisplay - 根据其 id 获取配方显示信息。
      • listDisplaysForRecipe - 接受要显示的配方的显示条目列表。
      • replaceRecipes 已移除
      • $CachedCheck#getRecipeFor 现在接受一个 ServerLevel 而不是 Level
      • $IngredientCollector - 一个从配方中提取原料并将其添加到 RecipePropertySet 的配方消费者
      • $IngredientExtractor - 一个在存在时获取配方的原料的方法。
      • $ServerDisplayInfo - 一个将显示条目链接到其配方持有者的记录。
    • RecipeMap - 一个通过配方类型和资源键映射配方持有者的类。
    • RecipePropertySet - 一组可用作给定配方槽位输入的原料。用于只允许特定输入到屏幕上的槽位。
    • SelectableRecipe - 一个包含槽位显示及其关联配方的记录。目前仅用于切石机菜单。
    • SimpleCookingSerializer -> AbstractCookingRecipe$Serializer
    • SingleItemRecipe 不再接受 RecipeTypeRecipeSerializer
      • ingredientresultgroup 现在是私有的
      • inputresult - 配方的槽位。
  • 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。虽然这可能不会被使用,但这是用来代替直接调用静态注册表来获取关联的 HolderHolderSet

  • 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
    • setShaderFogStartsetShaderFogEndsetShaderFogColorsetShaderFogShape -> setShaderFog
    • getShaderFogStartgetShaderFogEndgetShaderFogColorgetShaderFogShape -> 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#setFramerateLimitgetFramerateLimit 已移除
  • net.minecraft.client
    • InactivityFpsLimit - 一个枚举,定义了当窗口最小化或玩家离开键盘时如何限制 FPS。
    • Minecraft#getFramerateLimitTracker - 返回帧率限制器。

燃料值

FuelValues 已取代 AbstractFurnaceBlockEntity 中的静态映射。它的功能与该映射相同,只是燃料值存储在 MinecraftServer 本身上,并可提供给单个 Level 实例。可以通过访问 MinecraftServerLevel 并调用 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
      • invalidateCachegetFuel -> 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

朝向

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

  • net.minecraft.client.renderer.debug.RedstoneWireOrientationsRenderer - 红石线朝向的调试渲染器。
  • net.minecraft.world.level.Level
    • updateNeighborsAt - 使用指定的 Orientation 更新给定位置的邻居。
    • updateNeighborsAtExceptFromFacingneighborChanged 现在接受一个 Orientation
  • net.minecraft.world.level.block.RedStoneWireBlock
    • getBlockSignal - 返回方块信号的强度。
  • net.minecraft.world.level.block.state.BlockBehaviour
    • neighborChanged$BlockStateBase#handleNeighborChanged 现在接受一个 Orientation 而不是邻居 BlockPos
    • updateShape 现在接受 LevelReaderScheduledTickAccessRandomSource 而不是 LevelAccessorDirectionBlockState 参数的顺序已重新排列
    • $BlockStateBase#updateShape 现在接受 LevelReaderScheduledTickAccessRandomSource 而不是 LevelAccessorDirectionBlockState 参数的顺序已重新排列
  • net.minecraft.world.level.redstone
    • CollectingNeighborUpdater$ShapeUpdate#state -> neighborState
    • NeighborUpdater
      • neighborChangedupdateNeighborsAtExceptFromFacingexecuteUpdate 现在接受一个 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 - 设置矿车是否在铁轨上。
      • isFlippedsetFlipped - 返回矿车是否倒置。
      • getRedstoneDirection - 返回红石供电的方向。
      • isRedstoneConductor 现在是公开的
      • applyNaturalSlowdown 现在返回要减速的向量。
      • getPosOffs -> MinecartBehavior#getPos
      • setInitialPos - 设置矿车的初始位置。
      • createMinecart 在其创建中现在是抽象的,意味着它可以用于根据提供的参数创建任何矿车
      • getMinecartType 已移除
      • getPickResult 现在是抽象的
      • $TypegetMinecartTypeisRideableisFurnace 取代,不是一对一。
    • AbstractMinecartContainer(EntityType, double, double, double, Level) 已移除
    • MinecartBehavior - 包含实体在移动过程中应如何渲染和定位。
    • MinecartFurnace#xPushzPush -> 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 提供。

// 在某个 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#getCarvingMaskgetOrCreateCarvingMasksetCarvingMask 不再接受 GenerationStep$Carving
  • net.minecraft.world.level.levelgen.placement
    • CarvingMaskPlacement 类已移除
    • PlacementContext#getCarvingMask 不再接受 GenerationStep$Carving

可编解码的 JSON 重载监听器

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

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 现在接受 DynamicOpsCodec

连续执行器

ProcessorMailboxProcessorHandle 已被分别替换为 AbstractConsecutiveExecutorTaskScheduler。它们在使用上基本相同,只是可能方法名称不同。

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

生物转化

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

// 对于某个 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
    • registerEnderPearlderegisterEnderPearlgetEnderPearls - 处理玩家投掷的末影珍珠。
    • registerAndUpdateEnderPearlTicketplaceEnderPearlTicket - 处理投掷的末影珍珠的区域加载票。

分析器与 Tracy 客户端

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

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
      • getProfilergetProfilerSupplier -> 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 而不是参数到对象的映射
      • hasParamgetParametergetOptionalParametergetParamOrNull 可以通过 ContextMap 以不同的名称访问
      • $Builder#withParameterwithOptionalParametergetParametergetOptionalParameter 现在接受一个 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_WIDTHBACKGROUND_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#setTabListOrdergetTabListOrder - 处理玩家标签页中循环切换玩家的顺序。
  • 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 数组返回。
    • getCamXgetCamYgetCamZ - 返回平截头体相机坐标。
  • net.minecraft.client.renderer.chunk.CompileTaskDynamicQueue - 一个处理块渲染部分编译任务的同步队列。
  • net.minecraft.client.renderer.debug
    • ChunkCullingDebugRenderer - 用于当块被剔除时的调试渲染器。
    • DebugRenderer
      • renderAfterTranslucents - 在半透明渲染后渲染块剔除渲染器。
      • renderVoxelShape - 渲染体素形状的轮廓。
      • toggleRenderOctree - 切换是否渲染 OctreeDebugRenderer
    • OctreeDebugRenderer - 渲染部分节点的顺序。
  • net.minecraft.client.renderer.texture.AbstractTexture#defaultBlurgetDefaultBlur - 返回正在应用的模糊是否是默认模糊。
  • 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#getPositivegetNegativegetDirections - 获取沿轴的方向。
    • 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
      • absoluteAABBrelativeAABB - 在绝对坐标和相对于测试位置的坐标之间移动边界框
      • assertEntityData - 断言提供的块位置的实体匹配谓词。
      • hurt - 从某个来源对实体造成指定数量的伤害。
      • kill - 杀死实体。
    • GameTestInfo#getTestOrigin - 获取测试的生成结构的原点。
    • StructureUtils#getStartCorner - 获取要运行的测试的起始位置。
  • net.minecraft.network
    • FriendlyByteBuf
      • readVec3writeVec3 - 读取和写入向量的静态方法。
      • readContainerIdwriteContainerId - 读取和写入菜单标识符的方法。
      • readChunkPoswriteChunkPos - 读取和写入区块位置的方法。
    • 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 - 处理玩家标签页中循环切换玩家的顺序。
      • getLastClientInputsetLastClientInputgetLastClientMoveIntent - 处理服务器玩家如何解释客户端脉冲。
      • 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 之间交替的余弦函数。
      • packDegreesunpackDegrees - 将 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 - 获取玩家经过的所有方块,并检查实体是否在一个方块内,如果存在则将其添加到一个集合中。
      • oldPositionsetOldPosAndrotsetOldPossetOldRot - 更新实体最后位置和旋转的辅助方法。
      • getXRotgetYRot - 返回给定部分刻下实体的线性插值旋转。
      • 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#packPoiSection#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 时,玩家可以从菜单中丢弃物品。
      • getPermissionLevelhasPermissions - 返回玩家的权限。
    • 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
      • getOpenBundleModelFrontLocationgetOpenBundleModelBackLocation - 返回捆绑包的模型位置。
      • toggleSelectedItemhasSelectedItemgetSelectedItemgetSelectedItemStack - 处理捆绑包内的物品选择。
      • getNumberOfItemsToShow - 确定一次显示的捆绑包中的物品数量。
      • getByColor - 处理从捆绑包到染色捆绑包的可用链接。
      • getAllBundleItemColors - 返回所有染色捆绑包的流。
    • ItemStack
      • clearComponents - 清除对堆栈所做的补丁,而不是物品组件。
      • isBroken - 返回堆栈是否已损坏。
      • hurtWithoutBreaking - 损坏堆栈而不使其损坏。
      • getStyledHoverName - 获取堆栈的样式化名称组件。
  • net.minecraft.world.item.component.BundleContents
    • canItemBeInBundle - 物品是否可以放入捆绑包。
    • getNumberOfItemsToShow - 确定一次显示的捆绑包中的物品数量。
    • hasSelectedItemgetSelectedItem - 处理捆绑包内的物品选择。
  • net.minecraft.world.item.enchantment.EnchantmentHelper
    • createBook - 创建一个附魔书堆栈。
    • doPostAttackEffectsWithItemSourceOnBreak - 在物品损坏时,在攻击后应用附魔。
  • net.minecraft.world.level
    • BlockCollisions 有一个接受 CollisionContext 的构造函数
    • BlockGetter#boxTraverseBlocks - 返回在给定边界框中沿向量遍历的位置的迭代器。
    • CollisionGetter
      • noCollision - 返回实体与方块、实体以及如果提供的 booleantrue 则液体之间是否存在碰撞。
      • 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#getSeaLevelSurfaceSystem#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
      • addsubtract - 平移向量并返回一个新对象。
      • 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
      • getPixelRGBAsetPixelRGBA 现在是私有的。它们分别被 getPixelsetPixel 取代
      • getPixelsRGBA -> getPixels
    • Window#updateDisplay 现在接受一个 TraceyFrrameCapture,或 null
  • net.minecraft.Util
    • backgroundExecutorioPoolnonCriticalIoPool 现在返回 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 替代
      • 还有一个委托,在 ComponentdrawInBatch 方法中默认将逆深度布尔值设置为 true
    • $StringRenderOutput 现在接受 Font、一个可选背景颜色,以及一个布尔值,表示在绘制文本时是否应使用逆深度
    • $StringRenderOutput#finish 现在是包私有的
  • net.minecraft.client.gui.components
    • AbstractSelectionList
      • replaceEntries 现在是公开的
      • getRowTopgetRowBottom 现在是公开的
    • 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 是公共替代,接受 $GlyphInstanceMatrix4fVertexConsumer 和颜色整数
    • $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 -> renderSlotHighlightBackrenderSlotHighlightFront,现在是私有的
    • BookEditScreen 现在接受 WritableBookContent
    • AbstractSignEditScreen
      • sign 现在是 protected
      • renderSignBackground 不再接受 BlockState
    • EffectRenderingInventoryScreen -> Screen#hasActiveEffectsEffectsInInventory。不是一对一,因为 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
      • setGameTimesetDayTime -> setTimeFromServer
    • TagCollector -> RegistryDataCollector$TagCollector,现在是包私有的
  • net.minecraft.client.player
    • AbstractClientPlayer#getFieldOfViewModifier 现在接受一个布尔值表示相机是否在第一人称,以及一个浮点数表示部分刻
    • Input -> ClientInputnet.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
      • holderOwnerasLookup 已移除,因为 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.DustColorTransitionOptionsDustParticleOptions 现在接受表示 RGB 值的整数而不是 Vector3f
  • net.minecraft.data.loot
    • BlockLootSubProvider
      • HAS_SHEARS -> hasShears
      • createShearsOnlyDrop 现在是一个实例方法
    • EntityLootSubProvider
      • killedByFrogkilledByFrogVariant 现在接受 EntityType 注册表的获取器
      • createSheepTable -> createSheepDispatchPool,不是一对一,因为该表被替换为一个池构建器,给定一个染料颜色到战利品表的映射
  • net.minecraft.gametest.framework
    • GameTestHelper#assertEntityPresentassertEntityNotPresent 接受一个边界框而不是两个向量
    • GameTestInfo#getOrCalculateNorthwestCorner 现在是公开的
  • net.minecraft.network.chat.Component#score 现在接受一个 SelectorPattern
  • net.minecraft.network.chat.contents.ScoreContentsSelectorContents 现在是一个记录
  • net.minecraft.network.protocol.login.ClientboundGameProfilePacket -> ClientboundLoginFinishedPacket
  • net.minecraft.network.protocol.game
    • ClientboundMoveEntityPacket#getyRotgetxRot 现在返回一个 float 表示度数
    • ClientboundPlayerPositionPacket 现在是一个记录,接受一个表示变化的 PositionMoverotation
      • relativeArguments -> relatives
      • yRotxRot -> 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#getTagServerFunctionManager#getTag 返回一个命令函数列表
  • net.minecraft.server.level
    • ChunkHolder
      • blockChangedsectionLightChanged 现在返回 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 现在接受一个 ConsecutiveExecutorChunkTaskDispatcher 而不是分别接受 ProcessorMailboxProcessorHandle
  • net.minecraft.server.packs.resources.ProfiledReloadInstance$State 现在是一个记录
  • net.minecraft.sounds.SoundEvent 现在是一个记录
  • net.minecraft.tags
    • TagEntry$Lookup#element 现在接受一个 boolean 表示元素是否必需
    • TagLoader 现在接受一个 $ElementLookup,其功能与之前的函数参数相同
      • build 现在返回一个列表的值
      • loadAndBuild -> loadTagsFromNetworkloadTagsForExistingRegistriesloadTagsForRegistrybuildUpdatedLookups
    • 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
    • addToTagfromTag 现在接受一个 HolderLookup$Provider
  • net.minecraft.world.effect
    • MobEffect#applyEffectTickapplyInstantenousEffectonMobRemovedonMobHurt 现在接受 ServerLevel
    • MobEffectInstance#onMobRemovedonMobHurt 现在接受 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 已被标记为已弃用,将被 hurtServerhurtClient 取代
        • hurtOrSimulate 作为一个辅助方法,决定调用哪一个,也被标记为已弃用
      • spawnAtLocation 现在接受 ServerLevel
      • isInvulnerableTo -> isInvulnerableToBase,现在是 protected 和 final
        • isInvulnerableTo 已移至 LivingEntity#isInvulnerableTo
      • teleportSetPosition 现在是公开的,接受 PositionMoveRotationRelative 集而不是 DimensionTransition
      • createCommandSourceStack -> createCommandSourceStackForNameResolution,不是一对一,因为它接受 ServerLevel
      • mayInteract 现在接受 ServerLevel 而不是仅仅 Level
      • setOldRot 现在是公开的
      • changeDimension -> teleport,给定 TeleportTransition 返回 ServerPlayer
      • canChangeDimensions -> canTeleport
    • EntitySpawnReason#SPAWN_EGG -> SPAWN_ITEM_USE,不是一对一,因为这表示实体可以从任何物品生成
    • EntityType
      • createloadEntityRecursiveloadEntitiesRecursiveloadStaticEntity 现在接受一个 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
      • actuallyHurtdoHurtTarget 现在接受 ServerLevel
      • hasLineOfSight 重载,带有剪辑上下文和眼睛 Y 提供者
      • makePoofParticles 现在是公开的
    • Mob
      • pickUpItemwantsToPickUp 现在接受 ServerLevel
      • equipItemIfPossible 现在接受 ServerLevel
      • customServerAiStep 现在接受 ServerLevel
      • dropPreservedEquipment 现在接受 ServerLevel
    • NeutralMob
      • isAngryAtisAngryAtAllPlayers 现在接受 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
      • radiusXZradiusY -> Attributes#FOLLOW_RANGE
      • isMatchingEntity 现在接受一个 ServerLevel
    • Sensor
      • TARGETING_RANGE 现在是私有的
      • isEntityTargetableisEntityAttackableisEntityAttackableIgnoringLineOfSight 现在接受一个 ServerLevel
      • wasEntityAttackableLastNTicksrememberPositives 现在处理 BiPredicate 而不是 Predicate
  • net.minecraft.world.entity.ai.targeting.TargetingConditions
    • selector 现在接受一个 $Selector
      • 这是一个函数式接口,取代了之前的谓词,但多了一个 ServerLevel 参数
    • test 现在接受一个 ServerLevel
  • net.minecraft.world.entity.ai.village.poi.PoiRecord#codecPoiSection#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
      • 可通过 isInGroundsetInGround 受保护访问
    • 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#hurtEnemypostHurtEnemy 现在接受一个 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 已被拆分为两个方法:getFilteredSpawningCategoriesspawnForChunk
  • net.minecraft.world.level.biome#Biome#getPrecipitationAtcoldEnoughToSnowwarmEnoughToRainshouldMeltFrozenOceanIcebergSlightly 现在接受一个 int 表示生物群系的基础高度
  • net.minecraft.world.level.block
    • Block
      • shouldRenderFace 接受正在检查的面的相对状态,不再传入 BlockGetterBlockPos
      • 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
      • getOcclusionShapegetLightBlockpropagatesSkylightDown 只接受 BlockState,不接受 BlockGetterBlockPos
      • getLootTable 现在返回一个 Optional,也是一个 protected 字段 drops
      • $BlockStateBase#getOcclusionShapegetLightBlockgetFaceOcclusionShapepropagatesSkylightDownisSolidRender 不再接受 BlockGetterBlockPos
      • $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 -> markUnsavedtryMarkSaved
      • $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
      • hasDifferentLightPropertiesgetOcclusionShape 不再接受 BlockGetterBlockPos
      • getOpacity 不再接受 BlockPos
      • shapeOccludes 不再接受两个 long 表示打包的位置
  • net.minecraft.world.level.material
    • FlowingFluid
      • spread 现在接受当前位置的 BlockState
      • getSlopeDistance 之前的参数已被合并到一个 $SpreadContext 对象中
      • spreadgetNewLiquidcanConvertToSourcegetSpread 现在接受一个 ServerLevel
    • Fluid
      • tick 现在接受当前位置的 BlockState
      • tickrandomTick 现在接受 ServerLevel
    • FluidState
      • tick 现在接受当前位置的 BlockState
      • tickrandomTick 现在接受 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 -> scheduleSavesaveAndJoin
    • LevelData#getGameRules -> ServerLevelData#getGameRules
  • net.minecraft.world.phys.BlockHitResult 现在接受一个布尔值表示是否击中了世界边界
    • 添加了两个辅助方法 hitBorderisWorldBorderHit
  • 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
    • getRedOrLuminancegetGreenOrLuminancegetBlueOrLuminance
    • 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
      • getTempTargetaddTempTarget
    • PostPass
      • setOrthoMatrix
      • getFilterMode
  • net.minecraft.client.renderer.block.model.BlockModel#fromString
  • net.minecraft.client.renderer.texture
    • AbstractTexture#blurmipmap
    • TextureManager#bindForSetup
  • net.minecraft.commands.arguments.coordinates.WorldCoordinates#current
  • net.minecraft.core
    • Direction#fromDelta
    • Registry#getOrCreateTaggetTagNamesresetTags
  • 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
      • walkDist0walkDist
      • 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#setChasingisChasing
  • 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

Minecraft 1.21.2/3 -> 1.21.4 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

客户端物品

Minecraft 已将物品应如何渲染的查找和定义移到了自己的数据生成系统中,该系统被称为客户端物品,位于 assets/<namespace>/items/<path>.json。客户端物品类似于方块状态模型定义,但将来有可能包含更多信息。目前,它只是作为一个链接器,链接到用于渲染的模型。

所有客户端物品都包含一个使用 model 字段的 ItemModel$Unbaked。每个未烘焙模型都有一个关联的类型,该类型定义了物品应如何设置渲染,或在特定情况下如何渲染。这些 type 可以在 ItemModels 中找到。本文将介绍除一种类型外的所有类型,因为该未烘焙模型类型专门用于在选择物品时的捆绑包。

物品还包含一个 properties 字段,其中包含一些与元数据相关的参数。目前,它只指定了一个布尔值,当为 false 时,使手部立即交换当前持有的物品,而不是播放手部抬起的动画。

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "" // 在此处设置类型
        // 添加其他参数
    },
    "properties": {
        // 当为 false 时,禁用将此物品交换到手中时的动画
        "hand_animation_on_swap": false
    }
}

基本模型

基本模型定义由 minecraft:model 类型处理。它包含两个字段:model,用于定义模型 JSON 的相对位置;以及一个可选的 tints 列表,用于定义如何对每个索引进行染色。

model 指向模型 JSON,相对于 assets/<namespace>/models/<path>.json。在大多数情况下,客户端物品定义看起来像这样:

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:model",
        // 指向 'assets/examplemod/models/item/example_item.json'
        "model": "examplemod:item/example_item"
    }
}

染色源

在模型 JSON 中,一些元素面会有一个 tintindex 字段,它引用 minecraft:model 未烘焙模型类型中 tints 列表的某个索引。tints 列表是 ItemTintSource,它们都在 net.minecraft.client.color.item.* 中定义。所有定义的染色源都可以在 ItemTintSources 中找到,例如 minecraft:constant 用于常量颜色,或 minecraft:dye 用于使用 DataComponents#DYED_COLOR 的颜色,如果不存在则使用默认值。所有染色源都必须返回一个不透明的颜色,不过所有源通常通过调用 ARGB#opaque 来应用。

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:model",
        // 指向 'assets/examplemod/models/item/example_item.json'
        "model": "examplemod:item/example_item",
        // 要应用的 tints 列表
        "tints": [
            {
                // 当 tintindex: 0 时
                "type": "minecraft:constant",
                // 0x00FF00(或纯绿色)
                "value": 65280
            },
            {
                // 当 tintindex: 1 时
                "type": "minecraft:dye",
                // 0x0000FF(或纯蓝色)
                // 仅在未设置 `DataComponents#DYED_COLOR` 时调用
                "default": 255
            }
        ]
    }
}

要创建自己的 ItemTintSource,需要实现 calculate 方法,并注册与 type 字段关联的 MapCodeccalculate 接受当前的 ItemStack、等级和持有实体,并返回一个带有不透明 alpha 的 RGB 整数,定义层应如何染色。

然后,需要将 MapCodec 注册到 ItemTintSources#ID_MAPPER,但该字段默认是私有的,因此需要一些访问更改或反射。

// 物品源类
public record FromDamage(int defaultColor) implements ItemTintSource {

    public static final MapCodec<FromDamage> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
        instance.group(
            ExtraCodecs.RGB_COLOR_CODEC.fieldOf("default").forGetter(FromDamage::defaultColor)
        ).apply(instance, FromDamage::new)
    );

    public FromDamage(int defaultColor) {
        this.defaultColor = ARGB.opaque(defaultColor);
    }

    @Override
    public int calculate(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity) {
        return stack.isDamaged() ? ARGB.opaque(stack.getBarColor()) : defaultColor;
    }

    @Override
    public MapCodec<FromDamage> type() {
        return MAP_CODEC;
    }
}

// 然后,在某个暴露 ItemTintSources#ID_MAPPER 的初始化位置
ItemTintSources.ID_MAPPER.put(
    // 注册表名称
    ResourceLocation.fromNamespaceAndPath("examplemod", "from_damage"),
    // 映射编解码器
    FromDamage.MAP_CODEC
);
// 对于 'tints' 数组中的某个对象
{
    "type": "examplemod:from_damage",
    // 0x0000FF(或纯蓝色)
    // 仅在物品尚未损坏时调用
    "default": 255
}

范围属性模型

范围属性模型,由 minecraft:range_dispatch 未烘焙模型类型定义,与之前的物品覆盖系统最为相似。本质上,该类型定义了一些可以缩放的物品属性,以及一系列阈值和关联的模型。选择的模型是具有最接近且不超过属性值的阈值的模型(例如,如果属性值为 4,我们有阈值 35,则会选择 3,因为它是最接近且不超过的)。物品属性通过 RangeSelectItemModelProperty 定义,它接受堆栈、等级、实体和一些种子值,返回一个浮点数,通常根据实现缩放在 0 和 1 之间。所有属性都可以在 net.minecraft.client.renderer.item.properties.numeric.* 中找到,并在 RangeSelectItemModelProperties 中注册,例如 minecraft:cooldown 用于冷却时间百分比,或 minecraft:count 用于堆栈中的当前物品数量或标准化后的最大堆栈大小百分比。

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:range_dispatch",

        // 要使用的 `RangeSelectItemModelProperty`
        "property": "minecraft:count",
        // 乘以计算出的属性值的标量
        // 如果 count 为 0.3,scale 为 0.2,则检查的阈值为 0.3*0.2=0.06
        "scale": 1,
        "fallback": {
            // 如果没有匹配的阈值,则使用的后备模型
            // 可以是任何未烘焙模型类型
            "type": "minecraft:model",
            "model": "examplemod:item/example_item"
        },

        // ~~ 由 `Count` 定义的属性 ~~
        // 当为 true 时,使用其最大堆栈大小对计数进行归一化
        "normalize": true,

        // ~~ 包含阈值信息的条目 ~~
        "entries": [
            {
                // 当计数为其当前最大堆栈大小的三分之一时
                "threshold": 0.33,
                "model": {
                    // 可以是任何未烘焙模型类型
                }
            },
            {
                // 当计数为其当前最大堆栈大小的三分之二时
                "threshold": 0.66,
                "model": {
                    // 可以是任何未烘焙模型类型
                }
            }
        ]
    }
}

要创建自己的 RangeSelectItemModelProperty,需要实现 get 方法,并注册与 type 字段关联的 MapCodecget 接受堆栈、等级、实体和种子值,并返回一个任意浮点数,供范围分发模型解释。

然后,需要将 MapCodec 注册到 RangeSelectItemModelProperties#ID_MAPPER,但该字段默认是私有的,因此需要一些访问更改或反射。

// 范围属性类
public record AppliedEnchantments() implements RangeSelectItemModelProperty {

    public static final MapCodec<AppliedEnchantments> MAP_CODEC = MapCodec.unit(new AppliedEnchantments());

    @Override
    public float get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) {
        return (float) stack.getEnchantments().size();
    }

    @Override
    public MapCodec<AppliedEnchantments> type() {
        return MAP_CODEC;
    }
}

// 然后,在某个暴露 RangeSelectItemModelProperties#ID_MAPPER 的初始化位置
RangeSelectItemModelProperties.ID_MAPPER.put(
    // 注册表名称
    ResourceLocation.fromNamespaceAndPath("examplemod", "applied_enchantments"),
    // 映射编解码器
    AppliedEnchantments.MAP_CODEC
);
// 对于 'model' 中的某个客户端物品
{
    "type": "minecraft:range_dispatch",

    // 要使用的 `RangeSelectItemModelProperty`
    "property": "examplemod:applied_enchantments",
    // 乘以计算出的属性值的标量
    "scale": 0.5,
    "fallback": {
        // 如果没有匹配的阈值,则使用的后备模型
        // 可以是任何未烘焙模型类型
        "type": "minecraft:model",
        "model": "examplemod:item/example_item"
    },

    // ~~ 由 `AppliedEnchantments` 定义的属性 ~~
    // 无(构造函数无参数)

    // ~~ 包含阈值信息的条目 ~~
    "entries": [
        {
            // 当存在一个附魔时
            // 因为 1 * 标量 0.5 = 0.5
            "threshold": 0.5,
            "model": {
                // 可以是任何未烘焙模型类型
            }
        },
        {
            // 当存在两个附魔时
            "threshold": 1,
            "model": {
                // 可以是任何未烘焙模型类型
            }
        }
    ]
}

选择属性模型

选择属性模型,由 minecraft:select 未烘焙模型类型定义,在功能上类似于范围属性模型,但现在它根据某个属性(通常是枚举)进行切换。物品属性通过 SelectItemModelProperty 定义,它接受堆栈、等级、实体、一些种子值和当前显示上下文,以获取其中一个属性值。所有属性都可以在 net.minecraft.client.renderer.item.properties.select.* 中找到,并在 SelectItemModelProperties 中注册,例如 minecraft:block_state 用于指定方块状态属性的字符串值,或 minecraft:display_context 用于当前的 ItemDisplayContext

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:select",

        // 要使用的 `SelectItemModelProperty`
        "property": "minecraft:display_context",
        "fallback": {
            // 如果没有匹配的阈值,则使用的后备模型
            // 可以是任何未烘焙模型类型
            "type": "minecraft:model",
            "model": "examplemod:item/example_item"
        },

        // ~~ 由 `DisplayContext` 定义的属性 ~~
        // 无(构造函数无参数)

        // ~~ 基于可选择的属性的开关情况 ~~
        "cases": [
            {
                // 当显示上下文为 `ItemDisplayContext#GUI` 时
                "when": "gui",
                "model": {
                    // 可以是任何未烘焙模型类型
                }
            },
            {
                // 当显示上下文为 `ItemDisplayContext#FIRST_PERSON_RIGHT_HAND` 时
                "when": "firstperson_righthand",
                "model": {
                    // 可以是任何未烘焙模型类型
                }
            }
        ]
    }
}

要创建自己的 SelectItemModelProperty,需要实现 get 方法,并注册与 type 字段关联的 SelectItemModelProperty$Typeget 接受堆栈、等级、实体、种子值和显示上下文,并返回一个可编码的对象,供选择模型解释。

然后,需要将 MapCodec 注册到 SelectItemModelProperties#ID_MAPPER,但该字段默认是私有的,因此需要一些访问更改或反射。

// 选择属性类
public record StackRarity() implements SelectItemModelProperty<Rarity> {

    public static final SelectItemModelProperty.Type<StackRarity, Rarity> TYPE = SelectItemModelProperty.Type.create(
        // 此属性的映射编解码器
        MapCodec.unit(new StackRarity()),
        // 被选择对象的编解码器
        Rarity.CODEC
    );

    @Nullable
    @Override
    public Rarity get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed, ItemDisplayContext displayContext) {
        // 当为 null 时,使用后备模型
        return stack.get(DataComponents.RARITY);
    }

    @Override
    public SelectItemModelProperty.Type<StackRarity, Rarity> type() {
        return TYPE;
    }
}

// 然后,在某个暴露 SelectItemModelProperties#ID_MAPPER 的初始化位置
SelectItemModelProperties.ID_MAPPER.put(
    // 注册表名称
    ResourceLocation.fromNamespaceAndPath("examplemod", "rarity"),
    // 属性类型
    StackRarity.TYPE
);
// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:select",

        // 要使用的 `SelectItemModelProperty`
        "property": "examplemod:rarity",
        "fallback": {
            // 如果没有匹配的阈值,则使用的后备模型
            // 可以是任何未烘焙模型类型
            "type": "minecraft:model",
            "model": "examplemod:item/example_item"
        },

        // ~~ 由 `StackRarity` 定义的属性 ~~
        // 无(构造函数无参数)

        // ~~ 基于可选择的属性的开关情况 ~~
        "cases": [
            {
                // 当稀有度为 `Rarity#UNCOMMON` 时
                "when": "uncommon",
                "model": {
                    // 可以是任何未烘焙模型类型
                }
            },
            {
                // 当稀有度为 `Rarity#RARE` 时
                "when": "rare",
                "model": {
                    // 可以是任何未烘焙模型类型
                }
            }
        ]
    }
}

条件属性模型

条件属性模型,由 minecraft:condition 未烘焙模型类型定义,在功能上类似于范围属性模型,但现在它根据布尔值进行切换。这些通常与范围分发结合使用,例如拉弓时。物品属性通过 ConditionalItemModelProperty 定义,它接受堆栈、等级、实体、一些种子值和当前显示上下文,以获取一个 true 或 false 语句。所有属性都可以在 net.minecraft.client.renderer.item.properties.conditional.* 中找到,并在 ConditionalItemModelProperties 中注册,例如 minecraft:damaged 用于物品是否损坏,或 minecraft:has_component 用于是否具有给定的数据组件。

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:condition",

        // 要使用的 `SelectItemModelProperty`
        "property": "minecraft:damaged",

        // ~~ 由 `Damaged` 定义的属性 ~~
        // 无(构造函数无参数)

        // ~~ 布尔结果的含义 ~~
        "on_true": {
            // 可以是任何未烘焙模型类型
        },
        "on_false": {
            // 可以是任何未烘焙模型类型
        }
    }
}

要创建自己的 ConditionalItemModelProperty,需要实现 get 方法,并注册与 type 字段关联的 MapCodecget 接受堆栈、等级、实体、种子值和显示上下文,并返回一个布尔值,分别由 on_trueon_false 解释。

然后,需要将 MapCodec 注册到 ConditionalItemModelProperties#ID_MAPPER,但该字段默认是私有的,因此需要一些访问更改或反射。

// 谓词属性类
public record TimePeriod(int month, MinMaxBounds.Ints dates, boolean enabled) implements ConditionalItemModelProperty {

    public static final MapCodec<TimePeriod> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
        instance.group(
            Codec.intRange(1, 12).fieldOf("month").forGetter(TimePeriod::month),
            MinMaxBounds.Ints.CODEC.fieldOf("dates").forGetter(TimePeriod::dates)
        ).apply(instance, TimePeriod::new)
    );

    public TimePeriod(int month, MinMaxBounds.Ints dates) {
        this.month = month;
        this.dates = dates;

        Calendar cal = Calendar.getInstance();
        this.enabled = cal.get(Calendar.MONTH) + 1 == this.month
            && this.dates.matches(cal.get(Calendar.DATE));
    }

    @Override
    public boolean get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed, ItemDisplayContext context) {
        return this.enabled;
    }

    @Override
    public MapCodec<TimePeriod> type() {
        return MAP_CODEC;
    }
}

// 然后,在某个暴露 ConditionalItemModelProperties#ID_MAPPER 的初始化位置
ConditionalItemModelProperties.ID_MAPPER.put(
    // 注册表名称
    ResourceLocation.fromNamespaceAndPath("examplemod", "time_period"),
    // 映射编解码器
    TimePeriod.MAP_CODEC
);
// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:condition",

        // 要使用的 `SelectItemModelProperty`
        "property": "examplemod:time_period",

        // ~~ 由 `TimePeriod` 定义的属性 ~~
        // 七月
        "month": 7,
        "dates": {
            // 7 月 1 日至 14 日之间
            "min": 1,
            "max": 14
        },

        // ~~ 布尔结果的含义 ~~
        "on_true": {
            // 可以是任何未烘焙模型类型
        },
        "on_false": {
            // 可以是任何未烘焙模型类型
        }
    }
}

复合模型

复合模型,由 minecraft:composite 定义,本质上是其他模型类型的组合,用于渲染。具体来说,它设置了多个层,在渲染时将一个模型叠加在另一个模型之上。

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:composite",

        // 将按照在列表中出现的顺序进行渲染
        "models": [
            {
                // 可以是任何未烘焙模型类型
            },
            {
                // 可以是任何未烘焙模型类型
            }
        ]
    }
}

特殊动态模型

特殊动态模型,由 minecraft:special 未烘焙模型类型定义,是用于无等级渲染器的方块实体(例如箱子、旗帜等)的新系统。这些模型不存储烘焙模型,而是提供一个要调用的渲染方法。特殊模型包装器接受一个用于获取基本模型设置(不是元素)的基础模型和一个 SpecialModelRenderer。所有特殊模型渲染器都可以在 net.minecraft.client.renderer.special.* 中找到,并在 SpecialModelRenderers 中注册。

// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:special",

        // 从中读取粒子纹理和显示变换的模型
        "base": "minecraft:item/template_skull",
        "model": {
            // 要使用的特殊模型渲染器
            "type": "minecraft:head",

            // ~~ 由 `SkullSpecialRenderer.Unbaked` 定义的属性 ~~
            // 骷髅头的类型
            "kind": "wither_skeleton"
        }
    }
}

要创建自己的 SpecialModelRenderer,需要同时实现渲染器和 $Unbaked 模型,以便从 JSON 读取数据。$Unbaked 模型通过 bake 创建 SpecialModelRenderer,并使用其 typeMapCodec 进行注册。然后,SpecialModelRenderer 通过 extractArgument 从堆栈中提取渲染所需的数据,并将其传递给 render 方法。如果不需要从堆栈中获取任何信息,可以实现 NoDataSpecialModelRenderer

然后,需要将 MapCodec 注册到 SpecialModelRenderers#ID_MAPPER,但该字段默认是私有的,因此需要一些访问更改或反射。

如果您的物品是一个持有的方块,还需要将其添加到 SpecialModelRenderers#STATIC_BLOCK_MAPPING 中,以便在特定渲染场景下(例如在矿车中,或被末影人捡起)通过 BlockRenderDispatcher#renderSingleBLock 进行渲染。默认模型渲染器和特殊模型渲染器都会在此方法中被调用;允许同时渲染静态方块模型和动态特殊模型。由于此映射是不可变的,您需要替换它或挂钩到 SpecialBlockModelRenderer 并以某种方式添加到存储的映射中。

// 特殊渲染器
public record SignSpecialRenderer(WoodType defaultType, Model model) implements SpecialModelRenderer<WoodType> {

    // 渲染模型
    @Override
    public void render(@Nullable WoodType type, ItemDisplayContext displayContext, PoseStack pose, MultiBufferSource bufferSource, int light, int overlay, boolean hasFoil) {
        VertexConsumer consumer = Sheets.getSignMaterial(type).buffer(bufferSource, this.model::renderType);
        this.model.renderToBuffer(pose, consumer, light, overlay);
    }

    // 从堆栈中获取木材类型
    @Nullable
    @Override
    public WoodType extractArgument(ItemStack stack) {
        return (stack.getItem() instanceof BlockItem item && item.getBlock() instanceof SignBlock sign)
            ? sign.type() : this.defaultType;
    }

    // 从中读取 JSON 的模型
    public static record Unbaked(WoodType defaultType) implements SpecialModelRenderer.Unbaked {

        public static final MapCodec<SignSpecialRenderer.Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
            instance.group(
                WoodType.CODEC.fieldOf("default").forGetter(SignSpecialRenderer.Unbaked::defaultType)
            ).apply(instance, SignSpecialRenderer.Unbaked::new)
        );

        // 创建特殊模型渲染器,如果失败则返回 null
        @Nullable
        @Override
        public SpecialModelRenderer<?> bake(EntityModelSet modelSet) {
            return new SignSpecialRenderer(
                this.defaultType,
                SignRenderer.createSignModel(modelSet, defaultType, true)
            )
        }

        @Overrides
        public MapCodec<SignSpecialRenderer.Unbaked> type() {
            return MAP_CODEC;
        }
    }
}

// 然后,在某个暴露 SpecialModelRenderers#ID_MAPPER 的初始化位置
SpecialModelRenderers.ID_MAPPER.put(
    // 注册表名称
    ResourceLocation.fromNamespaceAndPath("examplemod", "sign"),
    // 映射编解码器
    SignSpecialRenderer.Unbaked.MAP_CODEC
);
// 假设我们也可以直接添加到 SpecialModelRenderers#STATIC_BLOCK_MAPPING
// 我们有一个方块 EXAMPLE_SIGN
SpecialModelRenderers.STATIC_BLOCK_MAPPING.put(
    // 作为物品具有特殊渲染的方块
    EXAMPLE_SIGN,
    // 要使用的未烘焙渲染器
    new SignSpecialRenderer.Unbaked(WoodType.BAMBOO)
);
// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "minecraft:special",

        // 从中读取粒子纹理和显示变换的模型
        "base": "minecraft:item/bamboo_sign",
        "model": {
            // 要使用的特殊模型渲染器
            "type": "examplemod:sign",

            // ~~ 由 `SignSpecialRenderer.Unbaked` 定义的属性 ~~
            // 如果找不到,则使用的默认木材类型
            "default": "bamboo"
        }
    }
}

渲染物品

现在,通过 ItemModelResolverItemStackRenderState 来渲染物品。这与 EntityRenderState 的工作方式类似:首先,ItemModelResolver 设置 ItemStackRenderState,然后通过 ItemStackRenderState#render 渲染状态。

让我们从 ItemStackRenderState 开始。对于渲染,我们只关心以下方法:isEmptyisGui3dusesBlockLighttransformrenderisEmpty 用于确定堆栈是否应该被渲染。然后,isGui3dusesBlockLighttransform 在其关联的上下文中用于正确定位要渲染的堆栈。最后,render 接受姿势堆栈、缓冲区源、打包光照和覆盖纹理,以在适当的位置渲染物品。

ItemModelResolver 负责设置渲染所需的 ItemStackRenderState 上的信息。这是通过 updateForLiving(用于活体实体持有的物品)、updateForNonLiving(用于其他类型的实体持有的物品)和 updateforTopItem(用于所有其他情况)完成的。updateForItem(前两个方法委托给它)接受渲染状态、堆栈、显示上下文、堆栈是否在左手、等级、实体和一些种子值。这将通过 ItemStackRenderState#clear 清除先前状态,然后通过委托给 ItemModel#update 来设置新状态。如果您不在渲染器上下文中(例如,方块实体、实体),则始终可以通过 Minecraft#getItemModelResolver 获取 ItemModelResolver

// 在最简单的形式中,假设您没有进行任何变换(您应该根据需要这样做)
public class ExampleRenderer {
    private final ItemStackRenderState state = new ItemStackRenderState();

    public void render(ItemStack stack, Level level, PoseStack pose, MultiBufferSource bufferSource) {
        // 首先更新渲染状态
        Minecraft.getInstance().getItemModelResolver().updateForTopItem(
            // 渲染状态
            this.state,
            // 用于更新状态的堆栈
            stack,
            // 要在其中渲染的显示上下文
            ItemDisplayContext.NONE,
            // 是否在实体的左手中(当未知时使用 false)
            false,
            // 当前等级(可以为 null)
            level,
            // 持有实体(可以为 null)
            null,
            // 任意种子值
            0
        );

        // 在此处执行任何所需的变换

        // 然后渲染状态
        this.state.render(
            // 带有所需变换的姿势堆栈
            pose,
            // 缓冲区源
            bufferSource,
            // 打包的光照值
            LightTexture.FULL_BRIGHT,
            // 覆盖纹理值
            OverlayTexture.NO_OVERLAY
        );
    }
}

自定义物品模型定义

要制作自定义物品模型定义,我们需要查看 ItemStackRenderState 中的更多方法,虽然您通常不会使用它们,但了解它们很有用:ensureCapacitynewLayer。这两个方法负责确保有足够的 ItemStackRenderState$LayerRenderState,如果您碰巧同时叠加多个模型的话。实际上,每次您计划在未烘焙模型中渲染某些东西时,都应该调用 newLayer。如果您计划将多个东西叠加在一起渲染,那么应该在调用 newLayer 之前使用计划渲染的层数设置 ensureCapacity

一个物品模型定义由 ItemModel 组成,它在功能上定义了一个“烘焙模型”及其用于序列化的 ItemModel$Unbaked

未烘焙变体有两个方法:bake,用于创建 ItemModel;以及 type,它引用要注册到 ItemModels#ID_MAPPERMapCodec,但该字段默认是私有的,因此需要一些访问更改或反射。bake 接受 $BakingContext,其中包含用于获取 BakedModelModelBaker、用于实体模型的 EntityModelSet 以及缺失的 ItemModel

烘焙变体只有一个方法 update,负责在 ItemStackRenderState 上设置所有必要的信息。模型本身不进行任何渲染。

public record RenderTypeModelWrapper(BakedModel model, RenderType type) implements ItemModel {

    // 更新渲染状态
    @Override
    public void update(ItemStackRenderState state, ItemStack stack, ItemModelResolver resolver, ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) {
        ItemStackRenderState.LayerRenderState layerState = state.newLayer();
        if (stack.hasFoil()) {
            layerState.setFoilType(ItemStackRenderState.FoilType.STANDARD);
        }
        layerState.setupBlockModel(this.model, this.type);
    }

    public static record Unbaked(ResourceLocation model, RenderType type) implements ItemModel.Unbaked {
        // 为编解码器创建渲染类型映射
        private static final BiMap<String, RenderType> RENDER_TYPES = Util.make(HashBiMap.create(), map -> {
            map.put("translucent_item", Sheets.translucentItemSheet());
            map.put("cutout_block", Sheets.cutoutBlockSheet());
        });
        private static final Codec<RenderType> RENDER_TYPE_CODEC = ExtraCodecs.idResolverCodec(Codec.STRING, RENDER_TYPES::get, RENDER_TYPES.inverse()::get);

        // 要注册的映射编解码器
        public static final MapCodec<RenderTypeModelWrapper.Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
            instance.group(
                ResourceLocation.CODEC.fieldOf("model").forGetter(RenderTypeModelWrapper.Unbaked::model),
                RENDER_TYPE_CODEC.fieldOf("render_type").forGetter(RenderTypeModelWrapper.Unbaked::type)
            )
            .apply(instance, RenderTypeModelWrapper.Unbaked::new)
        );

        @Override
        public void resolveDependencies(ResolvableModel.Resolver resolver) {
            // 解析模型依赖项,因此传入所有已知的资源位置
            resolver.resolve(this.model);
        }

        @Override
        public ItemModel bake(ItemModel.BakingContext context) {
            // 获取烘焙模型并返回
            BakedModel baked = context.bake(this.model);
            return new RenderTypeModelWrapper(baked, this.type);
        }

        @Override
        public MapCodec<RenderTypeModelWrapper.Unbaked> type() {
            return MAP_CODEC;
        }
    }
}

// 然后,在某个暴露 ItemModels#ID_MAPPER 的初始化位置
ItemModels.ID_MAPPER.put(
    // 注册表名称
    ResourceLocation.fromNamespaceAndPath("examplemod", "render_type"),
    // 映射编解码器
    RenderTypeModelWrapper.Unbaked.MAP_CODEC
);
// 对于某个物品 'examplemod:example_item'
// JSON 位于 'assets/examplemod/items/example_item.json'
{
    "model": {
        "type": "examplemod:render_type",
        // 指向 'assets/examplemod/models/item/example_item.json'
        "model": "examplemod:item/example_item",
        // 设置渲染时使用的渲染类型
        "render_type": "cutout_block"
    }
}
  • net.minecraft.client
    • ClientBootstrap - 注册支持客户端的映射;目前用于物品模型定义。
    • Minecraft
      • getEquipmentModels 已移除,只能在 EntityRendererProvider$Context#getEquipmentAssets 中直接访问
      • getItemModelResolver - 返回用于解析当前要在 ItemStackRenderState$LayerRenderState 中渲染的模型的更新器。
    • KeyMapping#get - 根据其翻译键获取按键映射。
  • net.minecraft.client.color.item
    • Constant - 用于对物品纹理进行染色的常量。
    • CustomModelDataSource - 根据 DataComponent#CUSTOM_MODEL_DATA 数据组件中的索引获取要染色的颜色。如果未找到索引或超出范围,则使用默认颜色。
    • Dye - 使用 DataComponent#DYED_COLOR 数据组件获取要染色的颜色。
    • Firework - 使用 DataComponent#FIRE_EXPLOSION 数据组件获取要染色的颜色。
    • GrassColorSource - 根据提供的温度和降水值获取要染色的颜色。
    • ItemColor -> ItemTintSource,不是一对一,因为通过在模型列表中提供多个 ItemTintSource 来设置索引。
    • ItemColors 类已移除,现在作为 ItemTintSource 进行数据生成
    • ItemTintSources - 用于在模型中对物品纹理进行染色的源的注册表。
    • MapColor - 使用 DataComponent#MAP_COLOR 数据组件获取要染色的颜色。
    • Potion - 使用 DataComponent#POTION_CONTENTS 数据组件获取要染色的颜色。
    • TeamColor - 根据持有实体的队伍颜色获取颜色。
  • net.minecraft.client.data.Main - 客户端数据生成的入口点。
  • net.minecraft.client.particle.BreakingItemParticle 现在接受 ItemStackRenderState 而不是 ItemStack
    • $ItemParticleProvider - 一个抽象的粒子提供者,提供一个计算 ItemStackRenderState 的简单方法。
  • net.minecraft.client.renderer
    • BlockEntityWithoutLevelRenderer 类已移除,被 NoDataSpecialModelRenderer 数据生成系统取代
    • ItemInHandRenderer 现在接受 ItemModelResolver
    • ItemModelShaper 已移除,因为这些方法在 ModelManager 中可用
    • Sheets
      • getBedMaterial - 根据染料颜色获取床的材质。
      • colorToResourceMaterial - 获取染料颜色的资源位置。
      • createBedMaterial - 根据染料颜色或资源位置创建床的材质。
      • getShulkerBoxMaterial - 根据染料颜色获取潜影盒的材质。
      • colorToShulkerMaterial - 获取潜影盒的染料颜色的资源位置。
      • createShulkerMaterial - 根据染料颜色或资源位置创建潜影盒的材质。
      • chestMaterial - 使用给定的资源位置为箱子创建一个新的材质。
    • SpecialBlockModelRenderer - 方块到物品变体特殊渲染器的映射。
  • net.minecraft.client.renderer.block.BlockRenderDispatcher 现在接受一个提供的 SpecialBlockModelRenderer 而不是 BlockEntityWithoutLevelRenderer
  • net.minecraft.client.renderer.block.model
    • BakedOverrides 类已移除,被 RangeSelectItemModelProperty 数据生成系统取代
    • BlockModel 现在接受 TextureSlots$Data 而不是材质映射,并且不再接受 ItemOverride 列表
      • MISSING_MATERIAL 已移除,被 minecraft:missingno 取代
      • textureMap -> textureSlots,现在是私有的,不是一对一
      • parent 现在是私有的,不是一对一
      • parentLocation 现在是私有的
      • hasAmbientOcclusion -> getAmbientOcclusion
      • isResolved 已移除
      • getOverrides 已移除
      • getParent - 返回未烘焙的父模型。
      • getTextureSlots - 返回模型的纹理数据。
      • getElements 现在是包私有的
      • $GuiLight -> UnbakedModel$GuiLight
    • FaceBakery
      • bakeQuad 现在是静态的
      • calculateFacing 现在是私有的
    • ItemModelGenerator 现在实现 UnbakedModel
    • ItemOverride 类已移除,被 RangeSelectItemModelProperty 数据生成系统取代
    • ItemTransforms 现在是一个记录
      • hasTransform 已移除
    • TextureSlots - 一个处理模型内纹理映射的类。数据从 $Data 读取,并作为 $SlotContents 存储,直到在烘焙过程中解析为 Material
    • UnbakedBlockStateModel 现在继承 ResolvableModel 而不是 UnbakedModel
      • bake - 将方块状态烘焙到其可选择的模型中。
    • Variant 现在是一个记录
  • net.minecraft.client.renderer.blockentity
    • BannerRenderer 现在有一个接受 EntityModelSet 的重载构造函数
      • renderInHand - 渲染旗帜的物品模型。
    • BedRenderer 现在有一个接受 EntityModelSet 的重载构造函数
      • renderInHand - 渲染床的物品模型。
    • BlockEntityRenderDispatcher(Font, EntityModelSet, Supplier<BlockRenderDispatcher>, Supplier<ItemRenderer>, Supplier<EntityRenderDispatcher>) -> BlockEntityRenderDispatcher(Font, Supplier<EntityModelSet>, BlockRenderDispatcher, ItemModelResolver, ItemRenderer, EntityRenderDispatcher)
      • renderItem 已移除,在其特定类中实现
    • BlockEntityRendererProvider 现在接受 ItemModelResolver
      • getItemModelResolver - 获取返回物品模型的解析器。
    • ChestRenderer#xmasTextures - 返回是否应在箱子上渲染圣诞纹理。
    • DecoratedPotRenderer 现在有一个接受 EntityModelSet 的重载构造函数
      • renderInHand - 渲染饰纹陶罐的物品模型。
    • ShulkerBoxRenderer 现在有一个接受 EntityModelSet 的重载构造函数
      • render - 渲染潜影盒。
      • $ShulkerBoxModel#animate 不再接受 ShulkerBoxBlockEntity
    • SkullblockRenderer#createSkullRenderers -> createModel,不是一对一
  • net.minecraft.client.renderer.entity
    • EntityRenderDispatcher 现在接受一个 IteModelResolver、一个提供的 EntityModelSet 而不是实例,以及一个 EquipmentAssetManager 而不是 EquipmentModelSet
    • EntityRendererProvider$Context 现在接受一个 ItemModelResolver 而不是 ItemRenderer,以及一个 EquipmentAssetManager 而不是 EquipmentModelSet
      • getItemRenderer -> getItemModelResolver,不是一对一
      • getEquipmentModels -> getEquipmentAssets
    • FishingHookRenderer - 返回钓鱼钩的持有手臂。
    • HumanoidMobRenderer
      • getArmPose - 返回实体的手臂姿势。
      • extractHumanoidRenderState 现在接受一个 ItemModelResolver
    • ItemEntityRenderer
      • getSeedForItemStack 已移除
      • renderMultipleFromCount 现在接受 ItemClusterRenderState,并移除了 ItemRendererItemStackBakedModel 和 3d 布尔值
    • ItemRenderer 不再实现 ResourceManagerReloadListener
      • 构造函数现在只接受 ItemModelResolver
      • render -> renderItem,不是一对一
      • renderBundleItem 已移除
      • getModelresolveItemModel 已移除
    • LivingEntityRenderer#itemRenderer -> itemModelResolver,不是一对一
    • OminousItemSpawnerRenderer 现在使用 ItemClusterRenderState
    • SkeletonRenderer#getArmPose -> AbstractSkeletonRenderer#getArmPose
    • SnowGolemRenderer 现在使用 SnowGolemRenderState
  • net.minecraft.client.renderer.entity.layers
    • CrossArmsItemLayer 现在使用 HoldingEntityRenderState
    • CustomHeadLayer 不再接受 ItemRenderer
    • DolphinCarryingItemLayer 不再接受 ItemRenderer
    • EquipmentLayerRenderer$TrimSpriteKey 现在接受 ResourceKey<EquipmentAsset>
      • textureId - 获取纹饰的纹理 id。
    • FoxHeldItemLayer 不再接受 ItemRenderer
    • ItemInHandLayer 现在使用 ArmedEntityRenderState
      • 构造函数不再接受 ItemRenderer
      • renderArmWithItem 不再接受 BakedModelItemStackItemDisplayContext,而是接受 ItemStackRenderState
    • LivingEntityEmissiveLayer 现在接受一个布尔值,确定该层是否始终可见
    • PandaHoldsItemLayer 不再接受 ItemRenderer
    • PlayerItemInHandLayer 不再接受 ItemRenderer
      • renderArmWithItem 不再接受 BakedModelItemStackItemDisplayContext,而是接受 ItemStackRenderState
    • SnowGolemHeadLayer 现在使用 SnowGolemRenderState
    • WitchItemLayer 不再接受 ItemRenderer
  • net.minecraft.client.renderer.entity.player.PlayerRenderer#getArmPose 现在是私有的
  • net.minecraft.client.renderer.entity.state
    • ArmedEntityRenderState - 一个用于在右手和左手持有物品的实体的渲染状态。
    • HoldingEntityRenderState - 一个用于持有单个物品的实体的渲染状态。
    • ItemClusterRenderState - 一个用于应多次渲染的物品的渲染状态。
    • ItemDisplayEntityRenderState#itemRenderStateitemModel -> item,不是一对一
    • ItemEntityRenderState#itemModelitem -> ItemClusterRenderState#item,不是一对一
    • ItemFrameRenderState#itemStackitemModel -> item,不是一对一
    • LivingEntityRenderState
      • headItemModelheadItem -> headItem,不是一对一
      • 手臂和手部方法已移至 ArmedEntityRenderState
    • OminousItemSpawnerRenderState -> ItemClusterRenderState
    • PlayerRenderState
      • mainHandStateoffHandState -> ArmedEntityRenderState 方法
      • heldOnHead - 表示玩家头上的物品堆栈。
    • SkeletonRenderState#isHoldingBow - 表示骷髅是否在持弓。
    • SnowGolemRenderState - 雪傀儡的渲染状态。
    • ThrownItemRenderState#itemitemModel -> item,不是一对一
    • WitchRenderState#isHoldingPotion - 女巫是否在持药水。
  • net.minecraft.client.renderer.item
    • BlockModelWrapper - 包含模型及其关联染色的基本模型定义。
    • BundleSelectedItemSpecialRenderer - 用于捆绑包选择的堆栈的特殊渲染器。
    • ClampedItemPropertyFunctionItemPropertyFunction -> 根据情况和属性,使用 .properties.numeric.*
    • ClientItem - 表示 assets/<modid>/items 中模型定义的基础物品。
    • CompositeModel - 将多个模型叠加在一起。
    • ConditionalItemModel - 根据布尔值显示不同模型的模型。
    • EmptyModel - 不渲染任何内容的模型。
    • ItemModel - 根据需要更新堆栈渲染状态的基础物品模型。
    • ItemModelResolver - 更新堆栈渲染状态的解析器。
    • ItemModels - 包含 ClientItem 的所有潜在物品模型。
    • ItemProperties 类已移除
    • ItemStackRenderState - 表示要渲染的堆栈的渲染状态。
    • MissingItemModel - 表示缺失模型的模型。
    • RangeSelectItemModel - 包含一定范围值的模型,应用满足阈值的关联模型。
    • SelectItemModel - 根据提供的属性进行切换的物品模型。
    • SpecialModelWrapper - 用于动态渲染的模型(例如箱子)的物品模型。
  • net.minecraft.client.renderer.item.properties.conditional
    • Broken - 如果物品只剩下一点耐久。
    • BundleHasSelectedItem - 如果捆绑包持有选中的物品。
    • ConditionalItemModelProperties - 包含所有潜在的条件属性类型。
    • ConditionalItemModelProperty - 表示返回某个布尔值的属性。
    • CustomModelDataProperty - 如果当前索引在 DataComponents#CUSTOM_MODEL_DATA 中被设置为 true。
    • Damaged - 如果物品已损坏。
    • ExtendedView - 如果显示上下文是 GUI 并且按下了 shift 键。
    • FishingRodCast - 如果鱼竿正在使用。
    • HasComponent - 是否具有关联的数据组件。
    • IsCarried - 如果物品正在当前菜单中被携带。
    • IsKeybindDown - 如果按键映射正在被按下。
    • IsSelected - 如果物品在快捷栏中被选中。
    • IsUsingItem - 如果物品正在被使用。
    • IsViewEntity - 持有实体是否是当前的相机实体。
  • net.minecraft.client.renderer.item.properties.numeric
    • BundleFullness - 基于捆绑包内容的阈值。
    • CompassAngle - 基于当前角度状态的阈值。
    • CompassAngleState - 基于指南针当前朝向目标角度的阈值。
    • Cooldown - 基于当前冷却百分比的阈值。
    • Count - 基于堆栈数量的阈值。
    • CrossbowPull - 基于弩被拉开的阈值。
    • CustomModelDataProperty - 如果当前索引在 DataComponents#CUSTOM_MODEL_DATA 中设置了阈值。
    • Damage - 基于剩余耐久百分比的阈值。
    • NeedleDirectionHelper - 一个抽象类,帮助将指针指向正确的方向。
    • RangeSelectItemModelProperties - 包含所有潜在的范围属性类型。
    • RangeSelectItemModelProperty - 表示返回某个浮点数阈值的属性。
    • Time - 基于当前时间的阈值。
    • UseCycle - 基于正在使用的堆栈中归一化到某个周期模数的剩余时间的阈值。
    • UseDuration - 基于正在使用的堆栈中剩余时间的阈值。
  • net.minecraft.client.renderer.item.properties.select
    • Charge - 基于弩的充能类型的情况。
    • ContextDimension - 基于物品当前所在维度的情况。
    • ContextEntityType - 基于持有实体类型的情况。
    • CustomModelDataProperty - 如果当前索引在 DataComponents#CUSTOM_MODEL_DATA 中被设置为字符串。
    • DisplayContext - 基于显示上下文的情况。
    • ItemBlockState - 基于从持有方块状态属性的物品中获取属性值的情况。
    • LocalTime - 基于简单日期格式模式的情况。
    • MainHand - 基于持有物品的手臂的情况。
    • SelectItemModelProperties - 包含所有潜在的选择情况属性类型。
    • SelectItemModelProperty - 表示返回某种选择情况的属性。
    • TrimMaterialProperty - 基于物品上纹饰材料的情况。
  • net.minecraft.client.renderer.special
    • BannerSpecialRenderer - 旗帜的物品渲染器。
    • BedSpecialRenderer - 床的物品渲染器。
    • ChestSpecialRenderer - 箱子的物品渲染器。
    • ConduitSpecialRenderer - 潮涌核心的物品渲染器。
    • DecoratedPotSpecialRenderer - 饰纹陶罐的物品渲染器。
    • HangingSignSpecialRenderer - 悬挂式告示牌的物品渲染器。
    • NoDataSpecialModelRenderer - 不需要从堆栈读取任何数据的物品渲染器。
    • ShieldSpecialRenderer - 盾牌的物品渲染器。
    • ShulkerBoxSpecialRenderer - 潜影盒的物品渲染器。
    • SkullSpecialRenderer - 骷髅头的物品渲染器。
    • SpecialModelRenderer - 表示从堆栈读取数据并渲染对象而不需要渲染状态的模型。
    • SpecialModelRenderers - 包含所有潜在的特殊渲染器。
    • StandingSignSpecialRenderer - 站立式告示牌的物品渲染器。
    • TridentSpecialRenderer - 三叉戟的物品渲染器。
  • net.minecraft.client.resources.model
    • BakedModel
      • isCustomRenderer 已移除,被特殊渲染器系统取代
      • overrides 已移除,被属性渲染器系统取代
    • BlockStateModelLoader 不再接受缺失模型
      • definitionLocationToBlockMapper 现在是私有的
      • loadBlockStateDefinitionStack 现在是私有的
      • loadBlockStates - 获取方块状态的已加载模型。
      • $LoadedBlockModelDefinition 现在是包私有的
      • $LoadedModel 现在接受 UnbakedBlockStateModel 而不是 UnbakedModel
      • $LoadedModels
        • forResolving - 返回所有需要解析的模型。
        • plainModels - 返回从模型位置到未烘焙模型的映射。
    • BuiltInModel 类已移除
    • ClientItemInfoLoader - 加载所有物品堆栈的所有模型。
    • EquipmentModelSet -> EquipmentAssetManager
    • ItemModel -> net.minecraft.client.renderer.item.ItemModel
    • MissingBlockModel#MISSING 现在是私有的
    • ModelBaker
      • sprites - 返回获取精灵的获取器。
      • rootName - 获取用于调试的模型名称。
    • ModelBakery(Map<ModelResourceLocation, UnbakedModel>, Map<ResourceLocation, UnbakedModel>, UnbakedModel) -> ModelBakery(EntityModelSet, Map<ModelResourceLocation, UnbakedBlockStateModel>, Map<ResourceLocation, ClientItem>, Map<ResourceLocation, UnbakedModel>, UnbakedModel)
      • bakeModels 现在返回一个 $BakingResult
      • getBakedTopLevelModels 已移除
      • $BakingResult - 包含所有已加载的模型。
      • $TextureGetter
        • get 现在接受 ModelDebugName 而不是 ModelResourceLocation
        • reportingMissingReference - 处理当纹理未设置时如何报告。
        • bind - 创建一个绑定到当前模型的独立获取器。
    • ModelDebugName - 返回用于调试的模型名称。
    • ModelDiscovery
      • registerStandardModels 已移除
      • registerSpecialModels - 添加系统加载的内部模型。
      • addRoot - 添加一个可以解析的新模型。
      • getUnreferencedModels - 返回已加载模型与已使用模型之间的差异。
      • getTopModels 已移除
    • ModelGroupCollector$GroupKey#create 现在接受 UnbakedBlockStateModel 而不是 UnbakedModel
    • ModelManager
      • specialBlockModelRenderer - 返回特殊方块模型的渲染器。
      • entityModels - 返回实体的模型集。
      • getItemProeprties - 根据其资源位置返回客户端物品的属性。
    • ModelResourceLocation#inventory 已移除
    • ResolvableModel - 基础模型,通常是未烘焙的,具有需要解析的引用。
    • SimpleBakedModel 字段现在都是私有的
      • bakeElements - 根据方块元素烘焙模型。
      • $Builder 不再有一个接受 BlockModel 的重载
    • SpecialModels 类已移除
    • SpriteGetter - 用于关联材质的图集精灵的获取器。
    • UnbakedModel 现在是一个 ResolvableModel
      • bake(ModelBaker, Function<Material, TextureAtlasSprite>, ModelState) -> bake(TextureSlots, ModelBaker, ModelState, boolean, boolean, ItemTransforms)
      • getAmbientOcclusiongetTopAmbientOcclusion - 返回是否应在物品上启用环境光遮蔽。
      • getGuiLightgetTopGuiLight - 返回 GUI 内的光照面。
      • getTransformsgetTopTransformgetTopTransforms - 返回基于显示上下文要应用的变换。
      • getTextureSlotsgetTopTextureSlots - 返回模型的纹理数据。
      • getParent - 返回此模型的父模型。
      • bakeWithTopModelValues - 烘焙模型。
  • net.minecraft.data.models.* -> net.minecraft.client.data.models.*
  • net.minecraft.world.item
    • BundleItem 不再接受任何 ResourceLocation
      • openFrontModelopenBackModel 已移除
    • CrossbowItem$ChargeType - 弩正在充能的物品。
    • DyeColor#getMixedColor - 返回最接近混合颜色的染料。
    • Item$Properties#overrideModel 已移除
    • SpawnEggItem 不再接受其染色颜色
      • getColor 已移除
  • net.minecraft.world.item.alchemy.PotionContents
    • getColor(*) 已移除
    • getColorOr - 获取药水的自定义颜色,如果不存在则获取默认颜色。
  • net.minecraft.world.item.component.CustomModelData 现在接受一个浮点数、标志、字符串和颜色的列表,用于根据提供的索引在自定义模型属性中使用
  • net.minecraft.world.item.equipment
    • ArmorMaterial 现在接受 ResourceKey<EquipmentAsset> 而不是仅仅模型 id
    • EquipmentAsset - 一个表示装备客户端信息键的标记
    • EquipmentAssets - 所有原版装备资源。
    • EquipmentModel -> net.minecraft.client.resources.model.EquipmentClientInfo
    • EquipmentModels -> net.minecraft.client.data.models.EquipmentAssetProvider,不是一对一
    • Equippable 现在接受 ResourceKey<EquipmentAsset> 而不是仅仅模型 id
      • $Builder#setModel -> setAsset
  • net.minecraft.world.item.equipment.trim
    • ArmorTrim#getTexture 已移除
    • TrimMaterial 不再接受物品模型索引,并且覆盖盔甲材料的键指向 ResourceKey<EquipmentAsset>
  • net.minecraft.world.level.FoliageColor
    • getEvergreenColor -> FOLIAGE_EVERGREEN
    • getBirchColor -> FOLIAGE_BIRCH
    • getDefaultColor -> FOLIAGE_DEFAULT
    • getMangroveColor -> FOLIAGE_MANGROVE
  • net.minecraft.world.level.block.RenderShape#ENTITYBLOCK_ANIMATED 已移除
  • net.minecraft.world.level.block.entity
    • BannerBlockEntity#fromItem 已移除
    • BedBlockEntitty#setColor 已移除
    • BlockEntity#saveToItem 已移除
    • DecoratedPotBlockEntity#setFromItemgetPotAsItem 已移除
  • net.minecraft.world.level.storage.loot.functions.SetCustomModelDataFunction 现在接受一个浮点数、标志、字符串和颜色的列表,用于根据提供的索引在自定义模型属性中使用

生物 替换当前物品

与工具和盔甲分别是 DiggerItemArmorItem 子类型相关的最后一个硬编码实例已被重做:Mob#canReplaceCurrentItem。现在,它从 DataComponents#EQUIPPABLE 数据组件中读取堆栈的 EquipmentSlot。然后,根据情况使用不同的逻辑。

对于盔甲槽位,如果盔甲附有 EnchantmentEffectComponents#PREVENT_ARMOR_CHANGE 效果组件,则无法更换。否则,它将首先尝试比较盔甲属性,如果相等则比较盔甲韧性。

对于武器(通过手部槽位),它将首先检查生物是否有偏好的武器类型标签。如果有,它将把物品切换到标签中的武器,前提是标签中有一个物品而另一个没有。否则,它将尝试比较攻击伤害属性。

如果所有属性都相等,则它们都将默认采用以下逻辑。首先,它会尝试选择附魔最多的物品。然后,它会尝试选择剩余耐久度最多的物品(原始值,而不是百分比)。最后,它会检查其中一个物品是否通过 DataComponents#CUSTOM_NAME 具有自定义名称。

一个小问题是,BambooSaplingBlockBambooStalkBLock 仍然硬编码检查主手物品是否为 SwordItem,尽管这将来可能会被替换为对 ToolMaterial#applySwordProperties 的更改。

粒子,通过渲染类型渲染

粒子现在使用 RenderType 进行渲染,而不是自己设置缓冲区构建器。唯一的特殊情况是 ParticleRenderType#CUSTOM,它允许模组制作者通过 Particle#renderCustom 实现自己的渲染;以及 ParticleRenderType#NO_RENDER,它不渲染任何内容。

要创建新的 ParticleRenderType,可以通过传入其名称(用于日志记录)和要使用的 RenderType 来创建。然后,在 Particle#getRenderType 中返回该类型。

public static final ParticleRenderType TERRAIN_SHEET_OPAQUE = new ParticleRenderType(
    "TERRAIN_SHEET_OPAQUE", // 通常是可识别的内容,例如字段名称
    RenderType.opaqueParticle(TextureAtlas.LOCATION_BLOCKS) // 要使用的 RenderType
);
  • net.minecraft.client.particle
    • CherryParticle -> FallingLeavesParticle,不是一对一,因为新类对其泛化有更大的配置
    • ItemPickupParticle 不再接受 RenderBuffers
    • Particle#renderCustom - 使用 ParticleRenderType#CUSTOM 渲染类型渲染粒子。
    • ParticleEngine#render(LightTexture, Camera, float) -> render(Camera, float, MutliBufferSource$BufferSource)
    • ParticleRenderType 现在是一个记录,接受名称和它使用的 RenderType

小幅迁移

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

SimpleJsonResourceReloadListener

SimpleJsonResourceReloadListener 现在接受一个转换器,用于将某个键映射到资源位置。已为注册表键提供了一个抽象。这是通过 FileToIdConverter 完成的,它本质上持有一个前缀和扩展名,应用于某个 ResourceLocation

// 我们假设这是一个服务器重载监听器(意味着在 'data' 文件夹中)
public class MyLoader extends SimpleJsonResourceReloadListener<ExampleObject> {

    public MyLoader() {
        super(
            // 用于编码/解码对象的编解码器
            ExampleObject.CODEC,
            // 文件转换器
            // 会将文件放置在 data/<namespace>/example/object/<path>.json
            FileToIdConverter.json(
                // 前缀
                "example/object"
            )
        );
    }

    // 下面相同
}
  • net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener 现在接受一个注册表的资源键,或者一个文件到 id 的转换器,而不仅仅是一个字符串
    • scanDirectory 现在接受一个注册表的资源键,或者一个文件到 id 的转换器,而不仅仅是一个字符串

MetadataSectionSerializer,被 Codec 取代

MetadataSectionSerializer 已被移除,转而使用 Codec 来序列化元数据部分。因此,所有 MetadataSectionSerializer 都已被其 MetadataSectionType 取代,它包含部分的名称和该元数据部分的编解码器。

  • net.minecraft.client.renderer.texture
    • HttpTexture -> SkinTextureDownloader,不是一对一,因为新类只是一个返回要存储内容的工具
    • MissingTextureAtlasSprite
      • getTexture -> generateMissingImage,不是一对一
      • getMissingImage(int, int) 现在是公开的
    • SpriteLoader#loadAndStitch 现在接受 MetadataSectionType 的集合而不是 MetadataSectionSerializer
  • net.minecraft.client.resources.SkinManager 不再接受 TextureManager
    • getOrLoad 现在返回一个 Optional<PlayerSkin> 的 future,而不仅仅是 PlayerSkin
  • net.minecraft.client.resources.metadata.animation
    • AnimationFrame 现在是一个记录
    • AnimationMetadataSection 现在是一个记录
    • AnimationMetadataSectionSerializer 类已移除
    • VillagerMetaDataSection -> VillagerMetadataSection
    • VillagerMetadataSectionSerializer 类已移除
  • net.minecraft.client.resources.metadata.texture
    • TextureMetadataSection 现在是一个记录
    • TextureMetadataSectionSerializer 类已移除
  • net.minecraft.server.packs.PackResources#getMetadataSection 现在接受 MetadataSectionType 而不是 MetadataSectionSerializer
  • net.minecraft.server.packs.metadata
    • MetadataSectionSerializer 已移除,转而使用部分编解码器
    • MetadataSectionType 现在是一个记录,而不是 MetadataSectionSerializer 的扩展
  • net.minecraft.server.packs.resources.ResourceMetadata
    • getSection 现在接受 MetadataSectionType 而不是 MetadataSectionSerializer
    • copySections 现在接受 MetadataSectionType 的集合而不是 MetadataSectionSerializer

音乐,现在带有音量控制

背景音乐现在通过 MusicInfo 类处理,它还存储音量以及关联的 Music

  • net.minecraft.client.Minecraft#getSituationalMusic 现在返回 MusicInfo 而不是 Music
  • net.minecraft.client.sounds
    • MusicInfo - 一个记录,包含当前正在播放的 Music 及其音量。
    • MusicManager#startPlaying 现在接受 MusicInfo 而不是 Music
    • SoundEngine#setVolumeSoundManager#setVolume - 设置关联声音实例的音量。
  • net.minecraft.world.level.biome
    • Biome
      • getBackgroundMusic 现在返回一个可选的 SimpleWeightedRandomList 的音乐。
      • getBackgroundMusicVolume - 获取背景音乐的音量。
    • BiomeSpecialEffects$Builder#silenceAllBackgroundMusicbackgroundMusic(SimpleWeightedRandomList<Music>) - 处理为生物群系设置背景音乐。

标签变更

  • minecraft:block
    • tall_flowers -> bee_attractive
  • minecraft:item
    • tall_flowersflowers 已移除
    • trim_templates 已移除
    • skeleton_preferred_weapons
    • drowned_preferred_weapons
    • piglin_preferred_weapons
    • pillager_preferred_weapons
    • wither_skeleton_disliked_weapons

新增列表

  • com.mojang.blaze3d.platform.Window#isMinimized - 返回应用程序窗口是否最小化。
  • com.mojang.blaze3d.vertex.VertexBuffer
    • uploadStatic - 通过使用带有 STATIC_WRITE VertexBufferTesselatorConsumer<VertexConsumer> 立即上传提供的顶点数据。
    • drawWithRenderType - 使用给定的 RenderType 将当前缓冲区绘制到屏幕。
  • com.mojang.math.MatrixUtil#isIdentity - 检查当前 Matrix4f 是否为单位矩阵。
  • net.minecraft
    • SuppressForbidden - 一个包含某些原因的注解,通常与需要 sysout 流有关。
    • Util#maxAllowedExecutorThreads - 返回在 1 和最大线程数之间钳制的可用处理器数量。
  • net.minecraft.client.gui.components.events.GuiEventListener#getBorderForArrowNavigation - 返回绑定到当前方向的 ScreenRectangle
  • net.minecraft.client.gui.navigation.ScreenRectangle#transformAxisAligned - 通过使用提供的 Matrix4f 变换位置来创建一个新的 ScreenRectangle
  • net.minecraft.client.gui.narration.NarratableEntry#getNarratables - 返回当前对象内可叙述对象的列表。
  • net.minecraft.client.gui.screens.recipebook.RecipeCollection#EMPTY - 一个空的配方集合。
  • net.minecraft.client.gui.screens.worldselection
    • ExperimentsScreen$ScrollArea - 表示当前可用实验的一个可叙述滚动区域。
    • SwitchGrid#layout - 返回要访问的网格布局。
  • net.minecraft.client.model
    • BannerFlagModelBannerModel - 旗帜和悬挂式旗帜的模型。
    • VillagerLikeModel#translateToArms - 平移姿势堆栈,使当前相对位置位于实体的手臂处。
  • net.minecraft.client.model.geom.EntityModelSet#vanilla - 创建一个包含所有原版模型的新模型集。
  • net.minecraft.client.multiplayer.PlayerInfo#setShowHatshowHat - 处理在标签页覆盖层中显示玩家的帽子层。
  • net.minecraft.client.renderer.blockentity
    • AbstractSignRenderer - 告示牌如何作为方块实体渲染。
    • HangingSignRenderer
      • createSignModel - 根据木材和附着位置创建一个告示牌模型。
      • renderInHand - 在实体手中渲染模型。
      • $AttachmentType - 一个枚举,根据其属性表示模型附着的位置。
      • $ModelKey - 模型的键,结合了 WoodType 及其 $AttachmentType
    • SignRenderer
      • renderInHand - 在实体手中渲染模型。
  • net.minecraft.client.renderer.entity.EntityRenderer#getShadowStrength - 返回显示阴影的原始不透明度。
  • net.minecraft.client.renderer.entity.layers.CrossedArmsItemLayer#applyTranslation - 应用平移以在模型的手臂中渲染物品。
  • net.minecraft.client.renderer.texture
    • ReloadableTexture - 可以从其关联内容重新加载的纹理。
    • TextureContents - 包含与给定纹理关联的图像和元数据。
    • TextureManager
      • registerAndLoad - 使用给定名称注册一个可重新加载的纹理。
      • registerForNextReload - 通过其资源位置注册一个纹理,以便在下一次重载时加载。
  • net.minecraft.commands.SharedSuggestionProvider#MATCH_SPLITTER - 定义一个匹配句点、下划线或正斜杠的匹配器。
  • net.minecraft.core.BlockPos$TraversalNodeStatus - 一个标记,指示 BlockPos 是否应被使用、跳过或停止任何进一步的遍历。
  • net.minecraft.core.component.PatchedDataComponentMap
    • toImmutableMap - 返回不可变的补丁或当前映射的副本。
    • hasNonDefault - 返回数据组件是否有自定义值而不是仅仅默认值。
  • net.minecraft.data.PackOutput$PathProvider#json - 从资源键获取 JSON 路径。
  • net.minecraft.data.loot.BlockLootSubProvider#createMultifaceBlockDrops - 根据挖掘的方块面掉落方块。
  • net.minecraft.data.worldgen.placement.PlacementUtils#HEIGHTMAP_NO_LEAVES - 使用 Heightmap$Types#MOTION_BLOCKING_NO_LEAVES 高度图创建一个 Y 轴放置。
  • net.minecraft.network.chat.Style#getShadowColorwithShadowColor - 处理组件阴影颜色的方法。
  • net.minecraft.network.protocol.game.ServerboundPlayerLoadedPacket - 当客户端玩家加载到客户端世界时发送的数据包。
  • net.minecraft.resources.FileToIdConverter#registry - 从注册表键获取文件转换器。
  • net.minecraft.util.ExtraCodecs
    • idResolverCodec - 创建一个将某个键映射到某个值的编解码器。
    • compactListCodec - 创建一个可以是元素或元素列表的编解码器。
    • floatRange - 创建一个必须在两个浮点值之间的编解码器。
    • $LateBoundIdMapper - 一个在功能上类似于具有关联编解码器的注册表的映射器。
  • net.minecraft.util.profiling.jfr.JvmProfiler#onStructureGenerate - 返回当结构尝试在世界中生成时的分析持续时间。
  • net.minecraft.util.profiling.jfr.event.StructureGenerationEvent - 当结构正在生成时的分析器事件。
  • net.minecraft.util.profiling.jfr.stats.StructureGenStat - 分析的结构生成的结果。
  • net.minecraft.world.entity
    • LivingEntity
      • resolvePlayerResponsibleForDamage - 获取对当前实体造成伤害的玩家。
      • canBeNameTagged - 当为 true 时,实体可以用命名牌设置名称。
    • Mob#getPreferredWeaponType - 获取表示实体想要拾取的武器的标签。
  • net.minecraft.world.entity.ai.attributes.AttributeMap#resetBaseValue - 将属性实例重置为其默认值。
  • net.minecraft.world.entity.monster.creaking
    • Creaking
      • activatedeactivate - 处理嘎枝的大脑逻辑的激活。
      • setTransientisHeartBoundsetHomePosgetHomePos - 处理家的位置。
      • blameSourceForDamage - 找到对伤害负责的玩家。
      • tearDown - 处理嘎枝被摧毁时的情况。
      • creakingDeathEffects - 处理嘎枝的死亡。
      • playerIsStuckInYou - 检查是否有至少四个玩家卡在嘎枝中。
      • setTearingDownisTearingDown - 处理拆除状态。
      • hasGlowingEyescheckEyeBlink - 处理眼睛状态。
  • net.minecraft.world.entity.player.Player
    • hasClientLoadedsetClientLoaded - 客户端玩家是否已加载。
    • tickClientLoadTimeout - Tick计时器,用于在客户端玩家未加载时等待多长时间后将其踢出。
  • net.minecraft.world.item
    • Item#shouldPrintOpWarning - 是否应根据存储的方块实体数据和管理员权限向玩家打印警告。
    • ItemStack
      • getCustomName - 返回物品的自定义名称,如果不存在组件则返回 null
      • immutableComponents - 返回不可变的补丁或堆栈组件映射的副本。
      • hasNonDefault - 返回数据组件是否有自定义值而不是仅仅默认值。
  • net.minecraft.world.item.component.CustomData
    • parseEntityId - 从组件中读取实体 id。
    • parseEntityType - 从 id 中读取实体类型,并将其映射到其注册表对象。
  • net.minecraft.world.item.crafting.Ingredient#isEmpty - 返回原料是否没有值。
  • net.minecraft.world.item.trading.Merchant#stillValid - 检查玩家是否仍然可以访问该商人。
  • net.minecraft.world.level
    • Level#dragonParts - 返回作为末影龙部件的实体列表。
    • ServerExplosion#getDamageSource - 返回爆炸的伤害来源。
  • net.minecraft.world.level.block
    • EyeblossomBlock$Type
      • block - 获取当前类型的方块。
      • state - 获取当前类型的方块状态。
      • transform - 返回此类型的相反状态。
    • FlowerBlock#getBeeInteractionEffect - 返回蜜蜂与花互动时获得的效果。
    • FlowerPotBlock#opposite - 返回方块的反向状态,仅适用于花盆中的 eyeblossom。
    • MultifaceBlock#canAttachTo - 返回此方块是否可以附着到另一个方块。
    • MultifaceSpreadeableBlock - 一个可以自然蔓延的多面方块。
  • net.minecraft.world.level.block.entity.trialspawner
    • TrialSpawner#overrideEntityToSpawn - 更改要在试炼中生成的实体。
    • TrialSpawnerConfig#withSpawning - 设置在试炼中生成的实体。

变更列表

  • com.mojang.blaze3d.platform.NativeImage#upload 不再接受三个设置 TEXTURE_2D 的过滤模式或纹理包裹钳位的布尔值
    • 这已移至 AbstractTexture#setClamp#setFilter
  • net.minecraft.client.gui
    • Gui#clear -> clearTitles
    • GuiGraphics#drawWordWrap 有一个新的重载,接受是否应对文本应用阴影
      • 默认版本启用阴影而不是禁用它
  • net.minecraft.client.gui.components
    • AbstractContainerWidget 现在实现 AbstractScrollArea
    • AbstractScrollWidget -> 根据用例使用 AbstractScrollAreaAbstractTextAreaWidget,不是一对一
    • AbstractSelectionList
      • setRenderHeader 现在被捆绑到一个带有额外整数的新构造函数中
      • getMaxScroll -> AbstractScrollArea#maxScrollAmount
      • getScrollAmount -> AbstractScrollArea#scrollAmount
      • scrollbarVisible -> AbstractScrollArea#scrollbarVisible
      • setClampedScrollAmountsetScrollAmount -> AbstractScrollArea#setScrollAmount
      • clampScrollAmount -> refreshScrollAmount
      • updateScrollingState -> AbstractScrollArea#updateScrolling
      • getScrollbarPositiongetDefaultScrollbarPosition -> scrollBarY,不是一对一
    • AbstractWidget#clicked -> isMouseOver,已经存在
  • net.minecraft.client.gui.components.toasts.TutorialToast 现在在其构造函数中需要 Font 作为第一个参数
  • net.minecraft.client.gui.font.glyphs.BakedGlyph$Effect$GlyphInstance 现在接受文本阴影的颜色和偏移
  • net.minecraft.client.gui.screens
    • LoadingOverlay#registerTextures 现在接受 TextureManager 而不是 Minecraft 实例
    • TitleScreen#preloadResources -> registerTextures,不是一对一
  • net.minecraft.client.gui.screens.debug.GameModeSwitcherScreen$GameModeSlot 现在是一个静态内部类
  • net.minecraft.client.gui.screens.reporting.ChatSelectionScreen$Entry$PaddingEntry 现在是静态内部类
  • net.minecraft.client.gui.screens.worldselection.SwitchGrid$Builder#build 不再接受 Consumer<LayoutElement>
  • net.minecraft.client.model
    • DonkeyModel#createBodyLayercreateBabyLayer 现在接受一个缩放因子
    • VillagerHeadModel -> VillagerLikeModel
  • net.minecraft.client.model.geom.EntityModelSet 不再是 ResourceManagerReloadListener
  • net.minecraft.client.multiplayer.MultiPlayerGameMode#handlePickItem -> handlePickItemFromBlockhandlePickItemFromEntity,同时提供要同步的实际对象数据和一个关于是否包含被拾取对象数据的 boolean
  • net.minecraft.client.particle.CherryParticle -> FallingLeavesParticle,不是一对一,因为新类对其泛化有更大的配置
  • net.minecraft.client.player.ClientInput#tick 不再接受任何参数
  • net.minecraft.client.renderer
    • CubeMap#preload -> registerTextures,不是一对一
    • LevelRenderer
      • renderLevel 不再接受 LightTexture
      • onChunkLoaded -> onChunkReadyToRender
    • PostChainConfig$Pass#program -> programId
      • program 现在返回具有给定 programIdShaderProgram
    • ScreenEffectRenderer#renderScreenEffect 现在接受一个 MultiBufferSource
    • SectionOcclusionGraph#onChunkLoaded -> onChunkReadyToRender
    • Sheets#createSignMaterialcreateHangingSignMaterial 现在有一个接受 ResourceLocation 的重载
    • SkyRenderer
      • renderSunMoonAndStarsrenderSunriseAndSunset 现在接受一个 MultiBufferSource$BufferSource 而不是 Tesselator
      • renderEndSky 不再接受 PoseStack
    • WeatherEffectRenderer#render 现在接受一个 MultiBufferSource$BufferSource 而不是 LightTexture
  • net.minecraft.client.renderer.blockentity
    • BannerRenderer#createBodyLayer -> BannerModel#createBodyLayer,不是一对一
    • HangingSignRenderer
      • createHangingSignLayer 现在接受一个 HangingSignRenderer$AttachmentType
      • $HangingSignModel 现在被 Model$Simple 取代,尽管其字段可以从根获取
    • SkullBlockRenderer#getRenderType 现在有一个接受 ResourceLocation 的重载,用于覆盖表示玩家纹理
  • net.minecraft.client.renderer.entity.AbstractHorseRendererDonkeyRenderer 不再接受浮点缩放
  • net.minecraft.client.renderer.entity.layers.CrossedArmsItemLayer 现在要求泛型 MVillagerLikeModel
  • net.minecraft.client.renderer.entity.state.CreakingRenderState#isActive -> eyesGlowing
    • 原始参数仍然存在于 Creaking 上,但对于渲染不是必需的
  • net.minecraft.core.BlockPos#breadthFirstTraversal 现在接受一个返回 $TraversalNodeStatus 的函数,而不是一个简单的谓词,以允许跳过某些位置
  • net.minecraft.core.particles.TargetColorParticleOption -> TrailParticleOption,不是一对一
  • net.minecraft.data.DataProvider#savelAll 现在有接受带有键函数的映射的重载,以获取关联的路径
  • net.minecraft.network
    • NoOpFrameEncoderLocalFrameEncoder 取代,不是一对一
    • NoOpFrameDecoderLocalFrameDecoder 取代,不是一对一
    • MonitorFrameDecoderMonitoredLocalFrameDecoder 取代,不是一对一
  • net.minecraft.network.protocol.game
    • ClientboundLevelParticlesPacket 现在接受一个布尔值,确定粒子是否应始终渲染
    • ClientboundMoveVehiclePacket 现在是一个记录
    • ClientboundPlayerInfoUpdatePacket$Entry 现在接受一个布尔值,表示是否应显示帽子
    • ClientboundSetHeldSlotPacket 现在是一个记录
    • ServerboundMoveVehiclePacket 现在是一个记录
    • ServerboundPickItemPacket -> ServerboundPickItemFromBlockPacketServerboundPickItemFromEntityPacket;不是一对一
  • `net.minecraft.server.level
    • ServerLevel#sendParticles 现在有一个接受覆盖限制距离和粒子是否应始终显示的重载
      • 其他接受覆盖限制器的重载现在也接受粒子是否应始终显示的布尔值
    • ServerPlayer#doCheckFallDamage -> Entity#doCheckFallDamage,现在是 final
  • net.minecraft.util
    • ARGB#from8BitChannel 现在是私有的,单个浮点分量可以通过 alphaFloatredFloatgreenFloatblueFloat 获得
    • SpawnUtil#trySpawnMob 现在接受一个布尔值,当为 false 时,允许实体无论与周围区域的碰撞状态如何都可以生成
  • net.minecraft.util.profiling.jfr.callback.ProfiledDuration#finish 现在接受一个布尔值,表示分析的事件是否成功
  • net.minecraft.util.profiling.jfr.parse.JfrStatsResults 现在接受一个结构生成统计信息的列表
  • net.minecraft.world.effect.PoisonMobEffectWitherMobEffect 现在是公开的
  • net.minecraft.world.entity
    • Entity
      • setOnGroundWithMovement 有一个重载,将水平碰撞设置为实体当前状态的任何值。
      • awardKillScore 不再接受整数
      • makeBoundingBox() 现在是 final
        • makeBoundingBox(Vec3) 现在
      • onlyOpCanSetNbt -> EntityType#onlyOpCanSetNbt
    • Leashable
      • readLeashData 现在是私有的,被一个不返回任何内容的方法取代
      • dropLeash(boolean, boolean) -> dropLeash()removeLeashonLeashRemoved;不是一对一,因为它们都在内部调用私有的 dropLeash
    • LivingEntity
      • isLookingAtMe 不再接受 Predicate<LivingEntity>,并且 DoubleSupplier 数组现在是一个 double 数组
      • hasLineOfSight 接受一个 double 而不是 DoubleSupplier
  • net.minecraft.world.entity.ai.behavior.AcquirePoi#create 现在有接受 BiPredicate<ServerLevel, BlockPos> 用于过滤 POI 位置的重载
  • net.minecraft.world.entity.animal.Bee#attractsBees 现在是公开的
  • net.minecraft.world.entity.monster.Shulker#getProgressAabbgetProgressDeltaAabb 现在接受一个移动 Vec3
  • net.minecraft.world.entity.player
    • Inventory
      • setPickedItem -> addAndPickItem
      • findSlotMatchingCraftingIngredient 现在接受一个 ItemStack 进行比较
    • Player#getPermissionLevel 现在是公开的
    • StackedContents$IngredientInfo 现在是一个接口,像一个接受某些物品的谓词
  • net.minecraft.world.entity.projectile.FishingHook 不再接受 ItemStack
  • net.minecraft.world.inventory.Slot#getNoItemIcon 现在返回单个 ResourceLocation 而不是一对
  • net.minecraft.world.item
    • Item$TooltipContext#of 现在接受查看物品的 Player
    • MobBucketItem 现在需要一个 Mob 实体类型 - SpawnEggItem#spawnsEntitygetType 现在接受一个 HolderLookup$Provider
  • net.minecraft.world.item.crafting
    • Ingredient 现在实现 StackedContents$IngredientInfo<Holder<Item>>
      • items 现在返回一个流而不是一个列表
    • PlacementInfo#slotInfo -> slotsToIngredientIndex,不是一对一
  • net.minecraft.world.level.Level#addParticle 现在接受一个布尔值,表示粒子是否应始终显示
  • net.minecraft.world.level.block
    • Block#getCloneItemStack -> state.BlockBehaviour#getCloneItemStack,现在是 protected
    • CherryLeavesBlock -> ParticleLeavesBlock
    • CreakingHeartBlock#canSummonCreaking -> isNaturalNight
    • MultifaceBlock 不再是抽象的,并且实现 SimpleWaterloggedBlock
      • getSpreader -> MultifaceSpreadeableBlock#getSpreader
    • SculkVeinBlock 现在是 MultifaceSpreadeableBlock 的一个实例
    • SnowyDirtBlock#isSnowySetting 现在是 protected
  • net.minecraft.world.level.block.entity
    • AbstractFurnaceBlockEntity
      • litTime -> litTimeRemaining
      • litDuration -> litTotalTime
      • cookingProgress -> cookingTimer
    • BeehiveBlockEntity#addOccupant 现在接受一个 Bee 而不是 Entity
    • CreakingHeartBlockEntity#setCreakingInfo - 设置方块实体所附着的嘎枝。
  • net.minecraft.world.level.block.state.BlockBehaviour#getCloneItemStack$BlockStateBase#getCloneItemStack 现在接受一个布尔值,表示是否有无限材料以及是否应保存当前方块数据。
  • net.minecraft.world.level.chunk.ChunkGenerator#createStructures 现在接受 Level 资源键,仅用于分析
  • net.minecraft.world.level.levelgen.feature.configurations
    • MultifaceGrowthConfiguration 现在接受 MultifaceSpreadableBlock 而不是 MultifaceBlock
    • SimpleBlockConfiguration 现在接受一个布尔值,表示是否安排Tick更新
  • net.minecraft.world.level.levelgen.structure.Structure#generate 现在接受 Structure 持有者和 Level 资源键,仅用于分析

移除列表

  • com.mojang.blaze3d.systems.RenderSystem#overlayBlendFunc
  • net.minecraft.client.gui.components.AbstractSelectionList
    • clickedHeader
    • isValidMouseClick
  • net.minecraft.client.gui.screens.recipebook.RecipeCollection#hasSingleResultItem
  • net.minecraft.client.model
    • DrownedModel#getArmPose,现在是 ArmedEntityRenderState 的一部分
    • FelineModel#CAT_TRANSFORMER
    • HumanoidModel#getArmPose,现在是 ArmedEntityRenderState 的一部分
    • PlayerModel#getArmPose,现在是 ArmedEntityRenderState 的一部分
    • SkeletonModel#getArmPose,现在是 ArmedEntityRenderState 的一部分
    • VillagerModel#BABY_TRANSFORMER
  • net.minecraft.client.renderer.texture
    • AbstractTexture
      • load
      • reset
      • getDefaultBlur
    • PreloadedTexture
    • TextureManager
      • getTexture(ResourceLocation, AbstractTexture)
      • register(String, DynamicTexture)
      • preload
  • net.minecraft.server.level.TicketType#POST_TELEPORT
  • net.minecraft.world.entity.LivingEntity#deathScore
  • net.minecraft.world.entity.ai.navigation.FlyingPathNavigationGroundPathNavigation
    • canPassDoorssetCanPassDoors
    • canOpenDoors
  • net.minecraft.world.entity.monster.creaking.CreakingTransient
  • net.minecraft.world.entity.player.StackedItemContents#convertIngredientContents
  • net.minecraft.world.item
    • CompassItem#getSpawnPosition
    • ItemStack#clearComponents
  • net.minecraft.world.item.crafting.PlacementInfo
    • ingredientToContents
    • unpackedIngredients
    • $SlotInfo
  • net.minecraft.world.level.block.CreakingHeartBlock$CreakingHeartState
  • net.minecraft.world.level.block.entity.BlockEntity#onlyOpCanSetNbt
  • net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerData#setEntityId

Minecraft 1.21.4 -> 1.21.5 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

感谢:

  • @TelepathicGrunt 提供的“非常技术性的变更”部分的信息
  • @RogueLogix 对“渲染管线重做”部分的审阅和评论
  • @Tslat 发现关于 equipOnInteract 的错误

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

正确处理方块实体的移除

以前,BlockEntity 会在 BlockBehaviour#onRemove 中处理其所有移除逻辑,包括丢弃任何存储的物品和移除方块实体本身。然而,根据方法的使用方式,由于方块实体的可变状态,可能会导致一些奇怪的行为。出于这个原因,构成移除过程的逻辑已被拆分为两个方法:BlockEntity#preRemoveSideEffectsBlockBehaviour#affectNeighborsAfterRemoval

BlockEntity#preRemoveSideEffects 现在负责在方块实体从等级中移除之前从中移除任何东西。默认情况下,如果 BlockEntity 是一个 Container 实例,它会将容器的内容丢弃到等级中。其他逻辑可以在这里处理,但它通常应避免移除 BlockEntity 本身,除非方块实体的位置倾向于动态变化,例如活塞。

然后,LevelChunk 逻辑将在调用 BlockBehaviour#affectNeighborsAfterRemoval 之前调用 removeBlockEntity。这应该只向其他方块发送更新,指示此方块已从等级中移除。对于 BlockEntity 持有者,可以通过调用 Containers#updateNeighboursAfterDestroy 轻松完成。否则,可能希望根据情况自己调用 Level#updateNeighborsAt

  • net.minecraft.world.Containers
    • updateNeighboursAfterDestroy - 在销毁指定位置的方块后更新邻居状态。
    • dropContentsOnDestroy 已移除,对于 Container 实例在 BlockEntity#preRemoveSideEffects 中处理
  • net.minecraft.world.level.block.entity.BlockEntity#preRemoveSideEffects - 处理在从等级中移除方块实体之前应发生的逻辑。
  • net.minecraft.world.level.block.state.BlockBehaviour#onRemove$BlockStateBase#onRemove -> affectNeighborsAfterRemoval,应只处理更新周围邻居的逻辑,而不是丢弃容器数据

体素形状辅助类

VoxelShape 获得了许多辅助方法,用于对其基本状态进行更常见的变换。有用于创建居中(如果需要)盒子的 Block 方法,以及用于将 VoxelShape 旋转到其适当轴或方向的 Shapes 方法。还有一个 Shapes#rotateAttachFace 方法,用于旋转附着在另一个方块面上的某个 VoxelShape。结果要么存储在某个键到 VoxelShapeMap 中,要么在使用 Block#getShapeForEachState 时存储为 Function<BlockState, VoxelShape>

大多数之前有公开或受保护 VoxelShapeBlock 子类现在都是私有的,重命名为通常称为 SHAPESHAPES 的字段。存储的 VoxelShape 也可能在 Function 中,而不是直接存储映射本身。

  • com.mojang.math.OctahedralGroup
    • permute - 返回给定轴在指定组内被置换到的轴。
    • fromAngles - 使用提供的 X 和 Y 旋转创建一个组。
  • net.minecraft.core.Direction$Axis#choose 现在有一个接受三个布尔值的重载
  • net.minecraft.world.level.block.Block
    • boxes - 创建比指定数量多一个的盒子,使用索引作为创建 VoxelShape 的函数的一部分。
    • cube - 创建一个指定大小的居中立方体。
    • column - 创建一个指定大小的水平居中柱体。
    • boxZ - 创建一个指定大小的垂直居中(围绕 X 轴)的立方体/柱体。
    • getShapeForEachState 现在返回一个包装 ImmutableMapFunction,还有一个方法只考虑指定的属性而不是所有可能的状态。
  • net.minecraft.world.phys.shapes
    • DiscreteVoxelShape#rotate - 根据 OctahedralGroup 的置换旋转体素形状。
    • Shapes
      • blockOccudes -> blockOccludes
      • rotate - 根据 OctahedralGroup 的置换围绕提供的向量(如果未指定则围绕方块中心)旋转给定的体素形状。
      • equal - 检查两个体素形状是否等效。
      • rotateHorizontalAxis - 创建一个轴到 VoxelShape 的映射,表示围绕 Y 轴旋转的方块。
      • rotateAllAxis - 创建一个轴到 VoxelShape 的映射,表示围绕任何轴旋转的方块。
      • rotateHorizontal - 创建一个方向到 VoxelShape 的映射,表示围绕 Y 轴旋转的方块。
      • rotateAll - 创建一个方向到 VoxelShape 的映射,表示围绕任何轴旋转的方块。
      • rotateAttachFace - 创建一个面到方向到 VoxelShape 的映射,表示当附着在其他方块面上时围绕 Y 轴旋转的方块。
    • VoxelShape#move 现在有一个接受 Vec3i 的重载

武器、工具和盔甲:去除冗余

武器、工具和盔甲有很多更新,分别移除了对 SwordItemDiggerItemArmorItem 硬编码基类的依赖。这些已被其关联的数据组件取代:WEAPON 用于伤害,TOOL 用于挖掘,ARMOR 用于保护,BLOCKS_ATTACKS 用于盾牌。此外,缺失的属性通常通过设置 ATTRIBUTE_MODIFIERSMAX_DAMAGEMAX_STACK_SIZEDAMAGEREPAIRABLEENCHANTABLE 来指定。鉴于几乎所有非特定逻辑都已移至数据组件,这些类现在已被完全移除。使用可用的物品属性方法之一或直接调用 Item$Properties#component 将每个物品设置为武器、工具、盔甲或三者的某种组合。

为类似盾牌的物品构造一个 BlockAttacks 组件:

var blocker = new BlocksAttacks(
    // 使用物品时,在格挡效果应用之前等待的秒数。
    1.2f,
    // 一个标量,用于更改格挡器被禁用的刻数。
    // 如果为负数,则格挡器通常不能被禁用。
    0.5f,
    // 一个减少量列表,说明此格挡器阻挡哪种伤害类型以及阻挡多少。
    List.of(
        new DamageReduction(
            // 应用减少量所需的盾牌水平格挡角度
            90f,
            // 此减少量应应用的伤害类型集合。
            // 当为空时,它适用于所有伤害类型。
            Optional.empty(),
            // 减少攻击的基础伤害。
            1f,
            // 表示被阻挡的伤害分数的标量。
            0.5f
        )
    ),
    // 一个函数,决定要从格挡器中移除多少耐久度。
    new ItemDamageFunction(
        // 指定从格挡器移除耐久度所需的最小伤害量的阈值。
        4f,
        // 从格挡器中移除的基础耐久度。
        1f,
        // 表示要转换为移除耐久度的伤害分数的标量。
        0.5f
    ),
    // 一个标签键,包含可以绕过格挡器并对持有实体直接造成伤害的物品。如果为空,则没有物品可以绕过格挡器。
    Optional.of(DamageTypeTags.BYPASSES_SHIELD),
    // 当格挡器成功减轻一些伤害时播放的声音。
    Optional.of(SoundEvents.SHIELD_BLOCK),
    // 当格挡器被武器禁用时播放的声音。
    Optional.of(SoundEvents.SHIELD_BREAK)
);

为类似剑的物品构造一个 Weapon 组件:

var weapon = new Weapon(
    // 从物品中移除的耐久度。
    3,
    // 当被此武器击中时,`BlocksAttack`s 组件物品应被禁用的秒数。
    5f
);
  • net.minecraft.core.component.DataComponents
    • UNBREAKABLE 现在是一个 Unit 实例
    • HIDE_ADDITIONAL_TOOLTIPHIDE_TOOLTIP 已被整合到 TOOLTIP_DISPLAY 中,接受一个 TooltipDisplay
    • BLOCKS_ATTACKS - 一个组件,决定持有的物品是否可以阻挡来自某些伤害源的攻击
    • INSTRUMENT 现在接受一个 InstrumentComponent
    • PROVIDES_TRIM_MATERIALPROVIDES_BANNER_PATTERNS 处理其关联类型的提供者。
    • BEES 现在接受一个 Bees 组件
    • BREAK_SOUND - 物品损坏时播放的声音。
  • net.minecraft.data.recipes
    • RecipeProvider#trimSmithing 现在接受 TrimPattern 的键
    • SmithingTrimRecipeBuilder 现在接受 TrimPattern 的持有者
  • net.minecraft.world.entity.LivingEntity
    • blockUsingShield -> blockUsingItem
    • blockedByShield -> blockedByItem
    • hurtCurrentlyUsedShield 已移除
    • canDisableBlocking -> getSecondsToDisableBlocking,不是一对一
    • applyItemBlocking - 应用用物品格挡攻击时所做的伤害减少。
    • isDamageSourceBlocked 已移除
  • net.minecraft.world.entity.player.Player#disableShield -> net.minecraft.world.item.component.BlocksAttacks#disable
  • net.minecraft.world.item
    • AnimalArmorItem 类已移除
    • ArmorItem 类已移除
    • AxeItem 现在继承 Item
    • BannerPatternItem 类已移除
    • DiggerItem 类已移除
    • FireworkStarItem 类已移除
    • HoeItem 现在继承 Item
    • InstrumentItem 不再接受标签键
    • Item
      • getBreakingSound 已移除
      • $Properties
        • tool - 将物品设置为工具。
        • pickaxe - 将物品设置为镐。
        • sword - 将物品设置为剑。
        • axe - 将物品设置为斧。
        • hoe - 将物品设置为锄。
        • shovel - 将物品设置为锹。
        • trimMaterial - 将物品设置为提供纹饰材料。
    • ItemStack#getBreakingSound 已移除
    • PickaxeItem 类已移除
    • ShovelItem 现在继承 Item
    • SwordItem 类已移除
    • ToolMaterial#applyToolProperties 现在接受一个布尔值,表示武器是否可以禁用格挡器(例如盾牌)
  • net.minecraft.world.item.component
    • Bees - 一个包含蜂巢居住者的组件。
    • BlocksAttacks - 用于用持有的物品格挡攻击的组件。
    • InstrumentComponent - 一个包含乐器播放声音的组件。
    • ProvidesTrimMaterial - 一个为某些盔甲提供要使用的纹饰材料的组件。
    • Tool 现在接受一个布尔值,表示该工具是否可以在创造模式下破坏方块
    • Unbreakable 类已移除
    • Weapon - 一个数据组件,包含物品可以造成多少伤害以及它禁用格挡器(例如盾牌)的时间。
  • net.minecraft.world.item.equipment
    • AllowedEntitiesProvider - 一个函数式接口,用于获取允许处理关联逻辑的实体。
    • ArmorMaterial
      • humanoidProperties -> Item$Properties#humanoidArmor
      • animalProperties -> Item$Properties#wolfArmorhorseArmor
      • createAttributes 现在是公开的
    • Equippable
      • equipOnInteract - 当为 true 时,该物品可以在与另一个实体交互时装备到该实体上。
      • saddle - 为马鞍创建一个可装备。
      • equipOnTarget - 将物品装备到目标实体上。

推断马鞍:装备变更

为马鞍添加了一个新的 EquipmentSlot,这带来了用于泛化槽位逻辑的新变化。

首先,现在可以通过一个称为 SimpleEquipmentLayer 的附加 RenderLayer 来处理实体的装备槽位渲染。这接受实体渲染器、EquipmentLayerRenderer、要渲染的层类型、从实体状态获取 ItemStack 的函数,以及成年和幼年模型。渲染器将尝试从关联的可装备数据组件中查找客户端信息,并使用该信息在必要时渲染层。

接下来,实体上不再为每个装备槽位设置单独的列表,而是有一个通用的 EntityEquipment 对象,它持有一个槽位到 ItemStack 的映射委托。这大大简化了存储逻辑。

最后,可装备现在可以通过设置 equipOnInteract 来指定物品是否应在交互时(通常是右键单击)装备到生物上。

  • net.minecraft.client.model
    • CamelModel
      • head 现在是公开的
      • createBodyMesh - 创建骆驼的网格定义。
    • CamelSaddleModel - 带有马鞍的骆驼模型。
    • DonkeyModel#createSaddleLayer - 为带有马鞍的驴创建层定义。
    • EquineSaddleModel - 带有马鞍的马科动物的模型。
    • PolarBearModel#createBodyLayer 现在接受一个布尔值,表示实体是否为幼年
  • net.minecraft.client.renderer.entity.layers.HorseArmorLayerSaddleLayer -> SimpleEquipmentLayer
  • net.minecraft.client.renderer.entity.state
    • CamelRenderState#isSaddled -> saddle,不是一对一
    • EquineRenderState#isSaddled -> saddle,不是一对一
    • PigRenderState#isSaddled -> saddle,不是一对一
    • SaddleableRenderState 类已移除
    • StriderRenderState#isSaddled -> saddle,不是一对一
    • CamelRenderState#isSaddled -> saddle,不是一对一
  • net.minecraft.client.resources.model.EquipmentClientInfo$LayerType 现在包含:
    • PIG_SADDLE
    • STRIDER_SADDLE
    • CAMEL_SADDLE
    • HORSE_SADDLE
    • DONKEY_SADDLE
    • MULE_SADDLE
    • ZOMBIE_HORSE_SADDLE
    • SKELETON_HORSE_SADDLE
    • trimAssetPrefix - 返回应用于包含关联类型的盔甲纹饰的纹理的前缀。
  • net.minecraft.world.entity
    • EntityEquipment - 一个槽位到物品堆栈的映射,表示实体的装备。
    • EquipmentSlot
      • SADDLE$Type#SADDLE
      • canIncreaseExperience - 该槽位是否可以在杀死生物时增加获得的经验值数量。
    • EquipmentSlotGroup 现在是一个可迭代对象
      • SADDLE
      • slots - 返回组内的槽位。
    • LivingEntity
      • getEquipSound - 获取将物品装备到槽位时要播放的声音。
      • getArmorSlotsgetHandSlotsgetArmorAndBodyArmorSlotsgetAllSlots 已移除
      • equipment - 实体穿戴的装备。
      • createEquipment - 设置实体穿戴的默认装备。
      • drop - 丢弃指定的堆栈。
      • getItemBySlotsetItemBySlot 不再是抽象的。
      • verfiyEquippedItem 已移除
    • Mob
      • isSaddled - 检查马鞍槽位中是否有物品。
      • createEquipmentSlotContainer - 为装备槽位创建一个单物品容器。
    • OwnableEntity#getRootOwner - 获取实体的最高级所有者。
    • Saddleable 接口已移除
  • net.minecraft.world.entity.animal.horse.AbstractHorse
    • syncSaddletoClients 已移除
    • getBodyArmorAccess 已移除
  • net.minecraft.world.entity.player
    • Inventory
      • armoroffhand -> EQUIPMENT_SLOT_MAPPING,不是一对一
      • selected 现在是私有的
      • setSelectedHotbarSlot -> setSelectedSlot
        • 还存在获取器 getSelectedSlot
      • getSelected -> getSelectedItem
        • 还存在设置器 setSelectedItem
      • getNonEquipmentItems - 返回库存中的非装备物品列表。
      • getDestroySpeed 已移除
      • getArmor 已移除
    • PlayerEquipment - 玩家穿戴的装备。
  • net.minecraft.world.item
    • Item#inventoryTick(ItemStack, Level, Entity, int, boolean) -> inventoryTick(ItemStack, ServerLevel, Entity, EquipmentSlot)
    • SaddleItem 类已移除

加权列表重做

加权随机列表已被重新设计为一个基本类,用于保存加权条目,以及一个辅助类,可以从对象本身获取权重。

首先是 WeightedList。它实际上是 SimpleWeightedRandomList 的替代品,通过将 WeightedWeightedEntry 的替代品)条目存储在列表本身中,以完全相同的方式工作。在内部,列表要么存储为对象条目的扁平数组,要么在总权重大于 64 时存储为紧凑加权列表。然后,要获取一个随机元素,可以调用 getRandomgetRandomOrThrow 来获取一个条目。如果列表中没有元素,这两个方法都将返回某种形式的空对象或异常。

然后是 WeightedRandom 中的静态辅助方法。这些方法接受原始列表和某个 ToIntFunction,该函数从列表的对象中获取权重。一些方法还接受一个整数,表示要选择的最大索引或与加权索引关联的条目。

  • net.minecraft.client.resources.model.WeightedBakedModel 现在接受 WeightedList 而不是 SimpleWeightedRandomList
  • net.minecraft.util.random
    • SimpleWeightedRandomListWeightedRandomList -> WeightedList,现在是 final,不是一对一
      • contains - 检查列表是否包含此元素。
    • Weight 类已移除
    • WeightedEntry -> Weighted
    • 所有 WeightedRandom 静态方法现在接受一个 ToIntFunction 来获取提供的列表中某个条目的权重
  • net.minecraft.util.valueproviders.WeightedListInt 现在接受 WeightedList
  • net.minecraft.world.level.SpawnData#LIST_CODEC 现在是一个 WeightedListSpawnData
  • net.minecraft.world.level.biome
    • Biome#getBackgroundMusic 现在是一个 WeightedListMusic
    • BiomeSpecialEffects#getBackgroundMusic$Builder#backgroundMusic 现在是一个 WeightedListMusic
    • MobSpawnSettings#EMPTY_MOB_LISTgetMobs 现在是一个 WeightedList
  • net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig#spawnPotentialsDefinitionlootTablesToEject 现在接受 WeightedList
  • net.minecraft.world.level.chunk.ChunkGenerator#getMobsAt 现在返回一个 WeightedList
  • net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider 现在使用 WeightedList
  • net.minecraft.world.level.levelgen.heightproviders.WeightedListHeight 现在使用 WeightedList
  • net.minecraft.world.level.levelgen.structure.StructureSpawnOverride 现在接受 WeightedList
  • net.minecraft.world.level.levelgen.structure.pools.alias
    • PoolAliasBinding#randomrandomGroup 现在接受 WeightedList
    • Random 现在接受 WeightedList
    • RandomGroup 现在接受 WeightedList
  • net.minecraft.world.level.levelgen.structure.structures.NetherFortressStructure#FORTRESS_ENEMIES 现在是一个 WeightedList

加载票

加载票已被重新实现为一个半类型注册表、半硬编码的系统。使区块在特定时间段内保持加载或模拟的底层逻辑仍然存在;然而,与每个加载票关联的逻辑被硬编码到它们适当的位置,例如强制加载或玩家加载加载票。

加载票从其注册的 TicketType 开始,其中包含有关加载票应持续多少刻(如果永久则为 0)、是否应将加载票保存到磁盘以及加载票的用途的信息。加载票有两种潜在用途:一种用于加载区块并保持其加载,另一种用于根据加载票创建者的预期移动来模拟区块。大多数加载票指定它们同时用于加载和模拟。

有两种特殊类型具有关联的额外行为。TicketType#FORCED 有一些立即加载区块并保持其加载的逻辑。TicketType#UNKNOWN 不能自动超时,意味着除非明确指定,否则它们永远不会被移除。

// 您需要将加载票类型注册到 `BuiltInRegistries#TICKET_TYPE`
public static final TicketType EXAMPLE = new TicketType(
    // 加载票被移除前的刻数
    // 如果不应移除,则设置为 0
    0L,
    // 是否应将加载票保存到磁盘
    true,
    // 加载票的用途
    TicketType.TicketUse.LOADING_AND_SIMULATION
);

然后是 Ticket 类,它实际存储在 TicketStorage 中并由其处理。Ticket 类接受加载票的类型,并使用它来自动填充它到期的时间。它还接受加载票等级,通常是一个值 31(用于实体Tick和方块Tick)、32(用于方块Tick)或 33(只能访问静态或修改,不能自然更新)减去可以加载的区块半径。然后通过调用 TicketStorage#addTicketWithRadius 或其委托 ServerChunkCache#addTicketWithRadius 将加载票添加到进程中。如果您希望手动指定加载票而不是根据其半径计算,也可以使用 addTicket

  • net.minecraft.server.level
    • ChunkMap 现在接受 TicketStorage
      • $TrackedEntity#broadcastIgnorePlayers - 将数据包广播给所有玩家,但 UUID 列表中的玩家除外。
    • DistanceManager
      • chunksToUpdateFutures 现在是 protected,并接受一个 TicketStorage
      • purgeStaleTickets -> net.minecraft.world.level.TicketStorage#purgeStaleTickets
      • getTicketDebugString -> net.minecraft.world.level.TicketStorage#getTicketDebugString
      • getChunkLevel - 返回当前区块等级,或当提供的布尔值为 true 时返回模拟等级。
      • getTickingChunks 已移除
      • removeTicketsOnClosing 已移除
      • $ChunkTicketTracker -> LoadingChunkTrackerSimulationChunkTracker
    • ServerChunkCache
      • addRegionTicket -> addTicketWithRadiusaddTicket
      • removeRegionTicket -> removeTicketWithRadius
      • removeTicketsOnClosing -> deactivateTicketsOnClosing
    • Ticket 不再是 final,也不再实现 Comparable
      • 构造函数不再接受键
      • CODEC
      • setCreatedTicktimedOut -> resetTicksLeftdecreaseTicksLeftisTimedOut;不是一对一
    • TicketType 现在是一个记录,不再有泛型
      • getComparator 已移除
      • doesLoaddoesSimulate - 检查加载票用途是否用于其特定实例。
      • $TicketUse - 加载票可以用于什么。
    • TickingTracker -> SimulationChunkTracker
  • net.minecraft.world.level.ForcedChunksSavedData -> TicketStorage
  • net.minecraft.world.level.chunk.ChunkSource
    • updateChunkForced 现在返回一个布尔值,指示区块是否已被强制加载
    • getForceLoadedChunks - 返回所有已被强制加载的区块。

游戏测试大修

游戏测试已被完全改造为一个基于注册表的系统,与之前自动注解驱动的系统完全不同。然而,使用该系统所需的大多数实现必须由您自己完成,而不是由原版提供。因此,此说明将涵盖整个系统,包括哪些部分需要大量工作才能使其类似于先前版本的注解驱动系统。

环境

所有游戏测试都在某个环境中发生。大多数情况下,测试可以独立于区域进行,但有时环境需要以某种方式进行管理,例如检查实体或方块在给定时间是否执行了某些操作。为了促进给定测试实例的环境设置和拆除,创建了一个 TestEnvironmentDefinition

TestEnvironmentDefinition 的工作方式类似于 BeforeBatchAfterBatch 注解。环境包含两个方法 setupteardown,用于管理测试的 ServerLevel。环境以基于类型的注册表系统构建,这意味着每个环境将一个 MapCodec 注册到内置注册表 minecraft:test_environment_definition_type,然后通过数据包注册表 minecraft:test_environment 中的 TestEnvironmentDefinition 使用。

默认情况下,原版提供了 minecraft:default 测试环境,它什么都不做。然而,可以使用可用的测试定义类型创建其他测试环境。

游戏规则

此环境类型设置测试要使用的游戏规则。在拆除期间,游戏规则将恢复为其默认值。

// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
    "type": "minecraft:game_rules",

    // 要设置的具有布尔值的游戏规则列表
    "bool_rules": [
        {
            // 规则的名称
            "rule": "doFireTick",
            "value": false
        }
        // ...
    ],

    // 要设置的具有整数值的游戏规则列表
    "int_rules": [
        {
            "rule": "playersSleepingPercentage",
            "value": 50
        }
        // ...
    ]
}

时间

此环境类型将时间设置为某个非负整数,类似于 /time set <number> 命令的使用方式。

// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
    "type": "minecraft:time_of_day",

    // 设置世界中的时间
    // 常见值:
    // - 白天      -> 1000
    // - 中午      -> 6000
    // - 夜晚      -> 13000
    // - 午夜      -> 18000
    "time": 13000
}

天气

此环境类型设置天气,类似于 /weather 命令的使用方式。

// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
    "type": "minecraft:weather",

    // 可以是三个值之一:
    // - clear   (无天气)
    // - rain    (雨)
    // - thunder (雷雨)
    "weather": "thunder"
}

函数

此环境类型提供两个 ResourceLocation 指向 mcfunctions,分别用于设置和拆除等级。

// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
    "type": "minecraft:function",

    // 要使用的设置 mcfunction
    // 如果未指定,则不会运行任何内容
    // 指向 'data/examplemod/function/example/setup.mcfunction'
    "setup": "examplemod:example/setup",

    // 要使用的拆除 mcfunction
    // 如果未指定,则不会运行任何内容
    // 指向 'data/examplemod/function/example/teardown.mcfunction'
    "teardown": "examplemod:example/teardown"
}

复合

如果需要多种组合,则可以使用复合环境类型(恰当地命名为 all_of)将上述多个环境类型串联在一起。

// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
    "type": "minecraft:all_of",

    // 要使用的测试环境列表
    // 可以指定注册表名称或环境本身
    "definitions": [
        // 指向 'data/minecraft/test_environment/default.json'
        "minecraft:default",
        {
            // 原始环境定义
            "type": "..."
        }
        // ...
    ]
}

自定义类型

如果上述类型都不起作用,则可以通过实现 TestEnvironmentDefinition 并创建关联的 MapCodec 来创建自定义定义:

public record ExampleEnvironmentType(int value1, boolean value2) implements TestEnvironmentDefinition {

    // 构造要注册的映射编解码器
    public static final MapCodec<ExampleEnvironmentType> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
            Codec.INT.fieldOf("value1").forGetter(ExampleEnvironmentType::value1),
            Codec.BOOL.fieldOf("value2").forGetter(ExampleEnvironmentType::value2)
        ).apply(instance, ExampleEnvironmentType::new)
    );

    @Override
    public void setup(ServerLevel level) {
        // 在此处设置任何必要的内容
    }

    @Override
    public void teardown(ServerLevel level) {
        // 撤消在 setup 方法中更改的任何内容
        // 这应恢复到默认值或之前的值
    }

    @Override
    public MapCodec<ExampleEnvironmentType> codec() {
        return CODEC;
    }
}

然后使用您的模组加载器所需的任何注册表方法注册 MapCodec

Registry.register(
    BuiltInRegistries.TEST_ENVIRONMENT_DEFINITION_TYPE,
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_environment_type"),
    ExampleEnvironmentType.CODEC
);

最后,您可以在环境定义中使用它:

// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
    "type": "examplemod:example_environment_type",

    "value1": 0,
    "value2": true
}

测试函数

游戏测试的最初概念是围绕运行 GameTestHelper 中的函数来判定测试成功或失败。测试函数是这些函数的注册表驱动表示。本质上,每个测试函数都是一个接受 GameTestHelper 的方法。

目前,原版只提供 minecraft:always_pass,它只调用 GameTestHelper#succeed。测试函数也不是生成的,意味着它只是用提供的任何内容运行该值。因此,一个测试函数通常应代表一个旧的游戏测试:

Registry.register(
    BuiltInRegistries.TEST_FUNCTION,
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_function"),
    (GameTestHelper helper) -> {
        // 运行您想要的任何游戏测试命令
        helper.assertBlockPresent(...);

        // 确保有某种方式成功
        helper.succeedIf(() -> ...);
    }
);

测试数据

现在我们有了环境和测试函数,就可以开始定义我们的游戏测试了。这是通过 TestData 完成的,它相当于 GameTest 注解。唯一的变化是,结构现在通过 structure 由其 ResourceLocation 引用,GameTest#timeoutTicks 现在重命名为 TestData#maxTicks,并且不再指定 GameTest#rotationSteps,而是通过 TestData#rotation 提供 Rotation。其他所有内容保持不变,只是以不同的格式表示。

游戏测试实例

有了 TestData,我们现在可以通过 GameTestInstance 将所有内容链接在一起。这个实例实际上代表了一个单独的测试。再次,原版只提供默认的 minecraft:always_pass,因此我们需要自己构造实例。

原始实例

以前的游戏测试使用 minecraft:function 实现,它将测试函数链接到测试数据。

// examplemod:example_test
// 在 'data/examplemod/test_instance/example_test.json'
{
    "type": "minecraft:function",

    // 指向测试函数注册表中的 'Consumer<GameTestHelper>'
    "function": "examplemod:example_function",

    // 'TestData' 信息

    // 运行测试的环境
    // 指向 'data/examplemod/test_environment/example_environment.json'
    "environment": "examplemod:example_environment",
    // 用于游戏测试的结构
    // 指向 'data/examplemod/structure/example_structure.nbt'
    "structure": "examplemod:example_structure",
    // 游戏测试将运行直到自动失败的刻数
    "max_ticks": 400,
    // 用于设置游戏测试所需所有内容的刻数
    // 这不计入测试可以进行的最大刻数
    // 如果未指定,默认为 0
    "setup_ticks": 50,
    // 测试是否必须成功才能将批次运行标记为成功
    // 如果未指定,默认为 true
    "required": true,
    // 指定结构和所有后续辅助方法应如何为测试旋转
    // 如果未指定,则不旋转任何内容
    "rotation": "clockwise_90",
    // 当为 true 时,测试只能通过 `/test` 命令运行
    // 如果未指定,默认为 false
    "manual_only": true,
    // 指定测试可以重新运行的最大次数
    // 如果未指定,默认为 1
    "max_attempts": 3,
    // 指定测试必须发生的最小成功次数,才能将测试标记为成功
    // 这必须小于或等于允许的最大尝试次数
    // 如果未指定,默认为 1
    "required_successes": 1,
    // 返回结构边界是否应保持顶部为空
    // 这目前仅用于基于方块的测试实例
    // 如果未指定,默认为 false 
    "sky_access": false
}

基于方块的实例

原版还通过 minecraft:block_based 提供了一个基于方块的测试实例。这是通过结构处理的,测试方块通过 Level#hasNeighborSignal 接收信号。要开始,结构必须有一个设置为启动模式的测试方块。然后触发该方块,发送一个持续一刻的十五信号脉冲。然后,结构可以有任意数量的测试方块,设置为日志、接受或失败模式。日志测试方块在激活时也会发送十五信号脉冲。接受和失败测试方块如果其中任何一个被激活,则游戏测试成功或失败(成功优先于失败)。

由于此测试依赖于结构中的测试方块,因此除了测试数据之外,不需要额外的信息:

// examplemod:example_test
// 在 'data/examplemod/test_instance/example_test.json'
{
    "type": "minecraft:block_based",

    // 'TestData' 信息

    // 指向 'data/examplemod/test_environment/example_environment.json'
    "environment": "examplemod:example_environment",
    // 指向 'data/examplemod/structure/example_structure.nbt'
    "structure": "examplemod:example_structure",
    "max_ticks": 400,
    "setup_ticks": 50,
    "required": true,
    "rotation": "clockwise_90",
    "manual_only": true,
    "max_attempts": 3,
    "required_successes": 1,
    "sky_access": false
}

自定义测试

如果您需要实现自己的基于测试的逻辑,无论是使用更动态的功能 还是因为您懒得将所有数据逻辑迁移到新系统,您可以通过扩展 GameTestInstance 并创建关联的 MapCodec 来创建自己的自定义测试实例:

public class ExampleTestInstance extends GameTestInstance {

    // 构造要注册的映射编解码器
    public static final MapCodec<ExampleTestInstance> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
            Codec.INT.fieldOf("value1").forGetter(test -> test.value1),
            Codec.BOOL.fieldOf("value2").forGetter(test -> test.value2),
            TestData.CODEC.forGetter(ExampleTestInstance::info)
        ).apply(instance, ExampleTestInstance::new)
    );

    public ExampleTestInstance(int value1, boolean value2, TestData<Holder<TestEnvironmentDefinition>> info) {
        super(info);
    }

    @Override
    public void run(GameTestHelper helper) {
        // 运行您想要的任何游戏测试命令
        helper.assertBlockPresent(...);

        // 确保有某种方式成功
        helper.succeedIf(() -> ...);
    }

    @Override
    public MapCodec<ExampleTestInstance> codec() {
        return CODEC;
    }

    @Override
    protected MutableComponent typeDescription() {
        // 提供关于此测试应该是什么的描述
        // 应使用可翻译组件
        return Component.literal("Example Test Instance");
    }
}

然后使用您的模组加载器所需的任何注册表方法注册 MapCodec

Registry.register(
    BuiltInRegistries.TEST_INSTANCE_TYPE,
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_test_instance"),
    ExampleTestInstance.CODEC
);

最后,您可以在测试实例中使用它:

// examplemod:example_test
// 在 'data/examplemod/test_instance/example_test.json'
{
    "type": "examplemod:example_test_instance",

    "value1": 0,
    "value2": true,

    // 'TestData' 信息

    // 指向 'data/examplemod/test_environment/example_environment.json'
    "environment": "examplemod:example_environment",
    // 指向 'data/examplemod/structure/example_structure.nbt'
    "structure": "examplemod:example_structure",
    "max_ticks": 400,
    "setup_ticks": 50,
    "required": true,
    "rotation": "clockwise_90",
    "manual_only": true,
    "max_attempts": 3,
    "required_successes": 1,
    "sky_access": false
}
  • net.minecraft.client.renderer.blockentity
    • BeaconRenderer 现在有一个泛型,接受 BlockEntityBeaconBeamOwner 的子类型
    • StructureBlockRenderer -> BlockEntityWithBoundingBoxRenderer,不是一对一
  • net.minecraft.core.registries.Registries#TEST_FUNCTIONTEST_ENVIRONMENT_DEFINITION_TYPETEST_INSTANCE_TYPE
  • net.minecraft.gametest.Main - 游戏测试服务器的入口点。
  • net.minecraft.gametest.framework
    • AfterBatchBeforeBatch 注解已移除
    • BlockBasedTestInstance - 用于测试测试方块的测试实例。
    • BuiltinTestFunctions - 包含所有已注册的测试函数。
    • FailedTestTracker - 用于保存所有失败的测试的对象。
    • FunctionGameTestInstance - 用于运行测试函数的测试实例。
    • GameTest 注解已移除
    • GameTestAssertException 现在继承 GameTestException
    • GameTestException - 游戏测试执行期间抛出的异常。
    • GameTestBatch 现在接受索引和环境定义,而不是名称和批次设置
    • GameTestBatchFactory
      • fromTestFunction -> divideIntoBatches,不是一对一
      • toGameTestInfo 已移除
      • toGameTestBatch 现在接受环境定义和索引
      • $TestDecorator - 从测试实例和等级创建测试信息列表。
    • GameTestEnvironments - 包含用于批处理游戏测试实例的所有环境。
    • GameTestGenerator 注解已移除
    • GameTestHelper
      • tickBlock - 在特定位置Tick方块。
      • assertionException - 返回一个在出错时要抛出的新异常。
      • getBlockEntity 现在接受一个 Class 来将方块实体转换为
      • assertBlockTag - 检查该位置的方块是否在提供的标签内。
      • assertBlock 现在接受一个方块 -> 组件函数,用于错误消息。
      • assertBlockProperty 现在接受 Component 而不是字符串
      • assertBlockState 现在接受什么都不接受、一个方块状态 -> 组件函数或一个提供的组件
      • assertRedstoneSignal 现在接受一个提供的组件
      • assertContainerSingle - 断言容器恰好包含一个指定物品。
      • assertEntityPositionassertEntityProperty 现在接受一个组件
      • fail 现在接受一个 Component 作为错误消息
      • assertTrueassertValueEqualassertFalse 现在接受一个组件
    • GameTestInfo 现在接受一个持有者包装的 GameTestInstance 而不是 TestFunction
      • setStructureBlockPos -> setTestBlockPos
      • placeStructure 现在不返回任何内容
      • getTestName - id,不是一对一
      • getStructureBlockPos -> getTestBlockPos
      • getStructureBlockEntity -> getTestInstanceBlockEntity
      • getStructureName -> getStructure
      • getTestFunction -> getTestgetTestHolder,不是一对一
      • getOrCalculateNorthwestCornersetNorthwestCorner 已移除
      • fail 现在接受 ComponentGameTestException 而不是 Throwable
      • getError 现在返回 GameTestException 而不是 Throwable
    • GameTestInstance - 定义要运行的测试。
    • GameTestInstances - 包含所有已注册的测试。
    • GameTestMainUtil - 用于运行游戏测试服务器的工具。
    • GameTestRegistry 类已移除
    • GameTestSequence
      • tickAndContinuetickAndFailIfNotComplete 现在接受一个整数作为刻,而不是 long
      • thenFail 现在接受一个提供的 GameTestException 而不是 Throwable
    • GameTestServer#create 现在接受一个可选的字符串和布尔值,而不是测试函数集合和起始位置
    • GeneratedTest - 一个包含要在给定环境下运行的测试和要应用的函数的对象
    • GameTestTicker$State - 一个枚举,包含游戏测试Tick器当前正在执行的状态。
    • GameTestTimeoutException 现在继承 GameTestException
    • ReportGameListener#spawnBeacon 已移除
    • StructureBlockPosFinder -> TestPosFinder
    • StructureUtils
      • testStructuresDir 现在是一个路径
      • getStructureBoundsgetStructureBoundingBoxgetStructureOriginaddCommandBlockAndButtonToStartTest 已移除
      • createNewEmptyStructureBlock -> createNewEmptyTest,不是一对一
      • getStartCornerprepareTestStructureencaseStructureremoveBarriers 已移除
      • findStructureBlockContainingPos -> findTestContainingPos
      • findNearestStructureBlock -> findNearestTest
      • findStructureByTestFunctioncreateStructureBlock 已移除
      • findStructureBlocks -> findTestBlocks
      • lookedAtStructureBlockPos -> lookedAtTestPos
    • TestClassNameArgument 已移除
    • TestEnvironmentDefinition - 定义测试运行的环境,通过在等级上适当设置数据。
    • TestFinder 不再包含上下文的泛型
      • $Builder#allTestsallTestsInClasslocateByName 已移除
      • $Builder#byArgument -> byResourceSelection
    • TestFunction -> TestData,不是一对一
    • TestFunctionArgument -> net.minecraft.commands.arguments.ResourceSelectorArgument
    • TestFunctionFinder -> TestInstanceFinder
    • TestFunctionLoader - 保存要加载和运行的测试函数列表。
    • UnknownGameTestException - 当游戏测试的错误未知时抛出的异常。
  • net.minecraft.network.protocol.game
    • ClientboundTestInstanceBlockState - 发送到客户端的数据包,包含测试的状态及其大小。
    • ServerboundSetTestBlockPacket - 发送到服务器的数据包,用于设置测试方块中要运行的信息。
    • ServerboundTestInstanceBlockActionPacket - 发送到服务器的数据包,用于在测试方块中设置测试实例。
  • net.minecraft.world.entity.player.Player
    • openTestBlock - 打开一个测试方块。
    • openTestInstanceBlock - 为游戏测试实例打开一个测试方块。
  • net.minecraft.world.level.block
    • TestBlock - 用于运行游戏测试的方块。
    • TestInstanceBlock - 用于管理单个游戏测试的方块。
  • net.minecraft.world.level.block.entity
    • BeaconBeamOwner - 一个接口,表示具有信标光束的方块实体。
    • BeaconBlockEntity 现在实现 BeaconBeamOwner
      • BeaconBeamSection -> BeaconBeamOwner$Section
    • BoundingBoxRenderable - 一个接口,表示可以渲染任意大小边界框的方块实体。
    • StructureBlockEntity 现在实现 BoundingBoxRenderable
    • TestBlockEntity - 用于运行游戏测试的方块实体。
    • TestInstanceBlockEntity - 用于管理单个游戏测试的方块实体。
  • net.minecraft.world.level.block.state.properties.TestBlockMode - 一个用于表示与测试方块关联的游戏测试当前状态的属性。

数据组件获取器

数据组件系统现在可以通过使用 DataComponentGetter 在任意对象上表示。顾名思义,获取器负责从关联的类型键获取组件。方块实体和实体都使用 DataComponentGetter 来允许查询内部数据,例如变体信息或自定义名称。它们都有从另一个持有者收集数据组件的方法(通过 applyImplicitComponentsapplyImplicitComponent)。方块实体还包含通过 collectImplicitComponents 收集到另一个持有者的方法。

物品

ItemSubPredicate 已被完全替换为 DataComponentPredicate。每个子谓词在系统中都有其适当的对应项。

  • net.minecraft.advancements.critereon.* -> net.minecraft.core.component.predicates.*
    • ItemAttributeModifiersPredicate -> AttributeModifiersPredicate
    • ItemBundlePredicate -> BundlePredicate
    • ItemContainerPredicate -> ContainerPredicate
    • ItemCustomDataPredicate -> CustomDataPredicate
    • ItemDamagePredicate -> DamagePredicate
    • ItemEnchantmentsPredicate -> EnchantmentsPredicate
    • ItemFireworkExplosionPredicate -> FireworkExplosionPredicate
    • ItemFireworksPredicate -> FireworksPredicate
    • ItemJukeboxPlayablePredicate -> JukeboxPlayablePredicate
    • ItemPotionsPredicate -> PotionsPredicate
    • ItemSubPredicate -> DataComponentPredicate,不是一对一
      • SINGLE_STREAM_CODEC
    • ItemSubPredicates -> DataComponentPredicates,不是一对一
    • ItemTrimPredicate -> TrimPredicate
    • ItemWritableBookPredicate -> WritableBookPredicate
    • ItemWrittenBookPredicate -> WrittenBookPredicate
  • net.minecraft.advancements.critereon
    • BlockPredicate 现在接受一个 DataComponentMatchers 用于匹配任何委托的组件数据
    • DataComponentMatchers - 一个对 DataComponentGetter 进行操作的谓词,匹配提供者上的任何精确和部分组件数据。
    • EntityPredicate 现在接受一个 DataComponentMatchers 而不是 Optional<DataComponentExactPredicate>
    • ItemPredicate 现在接受一个 DataComponentMatchers 用于匹配任何委托的组件数据
    • NbtPredicate#matches 现在接受一个 DataComponentGetter 而不是 ItemStack
    • SingleComponentItemPredicate 现在实现 DataComponentPredicate 而不是 ItemSubPredicate
      • matches(ItemStack, T) -> matches(T)
  • net.minecraft.core.component
    • DataComponentPatch
      • DELIMITED_STREAM_CODEC
      • $CodecGetter - 获取给定组件类型的编解码器。
    • DataComponentPredicate -> DataComponentExactPredicate
      • isEmpty - 检查谓词内的预期组件列表是否为空。
  • net.minecraft.core.registries.Registries#ITEM_SUB_PREDICATE_TYPE -> DATA_COMPONENT_PREDICATE_TYPE,不是一对一
  • net.minecraft.world.item.AdventureModePredicate 不再接受一个布尔值来显示在工具提示中
  • net.minecraft.world.item
    • BannerItem#appendHoverTextFromBannerBlockEntityTag 已移除
    • Item#appendHoverText(ItemStack, Item.TooltipContext, List<Component>, TooltipFlag) -> appendHoverText(ItemStack, Item.TooltipContext, TooltipDisplay, Consumer<Component>, TooltipFlag),现已弃用
    • ItemStack
      • addToTooltip 现在是公开的
      • addDetailsToTooltip - 将物品的组件详细信息附加到工具提示。
    • JukeboxPlayable#showInTooltip 已移除
  • net.minecraft.world.item.component
    • BlockItemStateProperties 现在实现 TooltipProvider
    • ChargedProjectiles 现在实现 TooltipProvider
    • CustomData#itemMatcher 已移除
    • DyedItemColor#showInTooltip 已移除
    • FireworkExplosion#addShapeNameTooltip 已移除
    • ItemAttributeModifiers#showInTooltip 已移除
    • ItemContainerContents 现在实现 TooltipProvider
    • SeededContainerLoot 现在实现 TooltipProvider
    • TooltipDisplay - 一个组件,处理物品工具提示中应隐藏的内容。
    • TooltipProvider#addToTooltip 现在接受一个 DataComponentGetter
  • net.minecraft.world.item.enchantment.ItemEnchantments#showInTooltip 已移除
  • net.minecraft.world.item.equipment.trim.ArmorTrim#showInTooltip 已移除
  • net.minecraft.world.item.trading.ItemCost 现在接受 DataComponentExactPredicate 而不是 DataComponentPredicate
  • net.minecraft.world.level.block.Block#appendHoverText 已移除
  • net.minecraft.world.level.block.entity
    • BannerPatternLayers 现在实现 TooltipProvider
    • PotDecorations 现在实现 TooltipProvider
  • net.minecraft.world.level.saveddata.maps.MapId 现在实现 TooltipProvider

实体

由于 EntityPredicate 现在接受一个 DataComponentExactPredicate 来匹配实体上的槽位,一些用于实体变体的 EntitySubPredicate 已转换为存储在持有的物品上的数据组件。

  • net.minecraft.advancements.critereon
    • EntityPredicate 现在接受一个 DataComponentExactPredicate 来匹配检查的装备槽位
    • EntitySubPredicate
      • AXOLTOL -> DataComponents#AXOLOTL_VARIANT
      • FOX -> DataComponents#FOX_VARIANT
      • MOOSHROOM -> DataComponents#MOOSHROOM_VARIANT
      • RABBIT -> DataComponents#RABBIT_VARIANT
      • HORSE -> DataComponents#HORSE_VARIANT
      • LLAMA -> DataComponents#LLAMA_VARIANT
      • VILLAGER -> DataComponents#VILLAGER_VARIANT
      • PARROT -> DataComponents#PARROT_VARIANT
      • SALMON -> DataComponents#SALMON_SIZE
      • TROPICAL_FISH -> DataComponents#TROPICAL_FISH_PATTERNTROPICAL_FISH_BASE_COLORTROPICAL_FISH_PATTERN_COLOR
      • PAINTING -> DataComponents#PAINTING_VARIANT
      • CAT -> DataComponents#CAT_VARIANTCAT_COLLAR
      • FROG -> DataComponents#FROG_VARIANT
      • WOLF -> DataComponents#WOLF_VARIANTWOLF_COLLAR
      • PIG -> DataComponents#PIG_VARIANT
      • 使用变体子谓词的 register 已移除
      • catVariantfrogVariantwolfVariant 已移除
      • $EntityHolderVariantPredicateType$EntityVariantPredicateType 已移除
    • SheepPredicate 不再接受 DyeColor
  • net.minecraft.client.renderer.entity.state.TropicalFishRenderState#variant -> pattern
  • net.minecraft.core.component
    • DataComponentGetter - 一个从某个对象获取数据组件的获取器。
    • DataComponentHolderDataComponentMap 现在继承 DataComponentGetter
    • DataComponentExactPredicate 现在是一个 DataComponentGetter 的谓词
      • expect - 一个期望数据组件具有某个值的谓词。
      • test(DataComponentHolder) 已移除
    • DataComponents
      • SHEEP_COLOR - 绵羊的染料颜色。
      • SHULKER_COLOR - 潜影贝(盒)的染料颜色。
      • COW_VARIANT - 奶牛的变体。
      • CHICKEN_VARIANT - 鸡的变体。
      • WOLF_SOUND_VARIANT - 狼发出的声音。
  • net.minecraft.world.entity
    • Entity 现在实现 DataComponentGetter
      • applyImplicitComponents - 将获取器中的组件应用到实体上。这应由模组制作者覆盖。
      • applyComponentsFromItemStack - 将堆栈中的组件应用到实体上。
      • castComponentValue - 将对象的类型转换为组件类型。
      • setComponent - 将组件数据设置到实体上。
      • applyImplicitComponent - 将组件数据应用到实体上。这应由模组制作者覆盖。
      • applyImplicitComponentIfPresent - 如果获取器中存在该组件,则应用它。
    • EntityType#appendCustomNameConfig -> appendComponentsConfig
    • VariantHolder 接口已移除
      • 因此,相关实体上的所有 setVariant 方法都是私有的,而关联的数据也可以从 DataComponentGetter 获得
  • net.minecraft.world.entity.animal
    • CatVariant#CODEC
    • Fox$Variant#STREAM_CODEC
    • FrogVariant#CODEC
    • MushroomCow$Variant#STREAM_CODEC
    • Parrot$Variant#STREAM_CODEC
    • Rabbit$Variant#STREAM_CODEC
    • Salmon$Variant#STREAM_CODEC
    • TropicalFish
      • getVariant -> getPattern
      • $Pattern 现在实现 TooltipProvider
    • Wolf -> .wolf.Wolf
    • WolfVariant -> .wolf.WolfVariant,现在是一个记录,接受一个 $AssetInfo 和一个 SpawnPrioritySelectors
    • WolfVariants -> .wolf.WolfVariants
  • net.minecraft.world.entity.animal.axolotl.Axolotl$Variant#STREAM_CODEC
  • net.minecraft.world.entity.animal.horse
    • Llama$Variant#STREAM_CODEC
    • Variant#STREAM_CODEC
  • net.minecraft.world.entity.animal.wolf
    • WolfSoundVariant - 狼发出的声音。
    • WolfSoundVariants - 所有原版狼声音变体。
  • net.minecraft.world.entity.decoration.Painting
    • VARIANT_MAP_CODEC 已移除
    • VARIANT_CODEC 现在是私有的
  • net.minecraft.world.entity.npc.VillagerDataHolder#getVariantsetVariant 已移除
  • net.minecraft.world.entity.variant.VariantUtils- 用于获取实体变体信息的工具。
  • net.minecraft.world.item
    • ItemStack#copyFrom - 从获取器复制组件。
    • MobBucketItem#VARIANT_FIELD_CODEC -> TropicalFish$Pattern#STREAM_CODEC
  • net.minecraft.world.level.block.entity.BlockEntity#applyImplicitComponents 现在接受一个 DataComponentGetter
    • $DataComponentInput -> DataComponentGetter
  • net.minecraft.world.level.Spawner 方法现在接受 CustomData 而不是 ItemStack 本身

生成条件

为了允许实体在给定条件下随机生成变体,添加了一个名为 SPAWN_CONDITION_TYPE 的新注册表。这些接受 SpawnCondition:一个选择器,像一个谓词,接受上下文以查看给定的变体是否可以在那里生成。所有变体都被放入一个列表中,然后根据存储在 SpawnProritySelectors 中的选定优先级进行排序。优先级较高的将首先被检查,相同优先级的多个将按提供的顺序选择。然后,在相同优先级级别上,所有满足条件的变体将被随机选择。

// 对于某个存在生成条件的对象
[
    {
        // 正在检查的生成条件
        "condition": {
            "type": "minecraft:biome",
            // 将检查变体尝试生成的生物群系是否在森林中
            "biomes": "#minecraft:is_forest"
        },
        // 将首先检查此条件
        "priority": 1
    },
    {
        // 表示条件始终为真
        "priority": 0
    }
]
  • net.minecraft.core.registries.Registries#SPAWN_CONDITION_TYPE
  • net.minecraft.world.entity.variant
    • BiomeCheck - 一个生成条件,检查实体是否在给定的生物群系之一中。
    • MoonBrightnessCheck - 一个生成条件,检查月亮的亮度。
    • PriorityProvider - 一个基于某个优先级整数对条件选择器进行排序的接口。
    • SpawnCondition - 检查实体是否可以在该位置生成。
    • SpawnConditions - 可供选择的生成条件。
    • SpawnContext - 一个包含实体生成所在的当前位置、等级和生物群系的对象。
    • SpawnPrioritySelectors - 要针对实体检查的生成条件列表。用于在给定位置随机选择一个变体生成。
    • StructureCheck - 一个生成条件,检查实体是否在结构内。

变体数据包注册表

青蛙、猫、奶牛、鸡、猪、狼和狼的声音变体是数据包注册表对象,意味着现在大多数引用需要通过 RegistryAccessHolderLookup$Provider 实例来引用。

对于青蛙、猫或狼:

// 文件位于:
// - `data/examplemod/frog_variant/example_frog.json`
// - `data/examplemod/cat_variant/example_cat.json`
// - `data/examplemod/wolf_variant/example_wolf.json`
{
    // 指向 `assets/examplemod/textures/entity/cat/example_cat.png` 的纹理
    "asset_id": "examplemod:entity/cat/example_cat",
    "spawn_conditions": [
        // 此变体生成的条件
        {
            "priority": 0
        }
    ]
}

对于猪、奶牛或鸡:

// 文件位于:
// - `data/examplemod/pig_variant/example_pig.json`
// - `data/examplemod/cow_variant/example_cow.json`
// - `data/examplemod/chicken_variant/example_chicken.json`
{
    // 指向 `assets/examplemod/textures/entity/pig/example_pig.png` 的纹理
    "asset_id": "examplemod:entity/pig/example_pig",
    // 定义用于选择渲染猪变体的实体模型的 `PigVariant$ModelType`
    "model": "cold",
    "spawn_conditions": [
        // 此变体生成的条件
        {
            "priority": 0
        }
    ]
}

对于狼的声音变体:

// 文件位于:
// - `data/examplemod/wolf_sound_variant/example_wolf_sound.json``
{
    // 空闲时随机播放的声音事件的注册表名称
    "ambient_sound": "minecraft:entity.wolf.ambient",
    // 死亡时播放的声音事件的注册表名称
    "death_sound": "minecraft:entity.wolf.death",
    // 生气时空闲时随机播放的声音事件的注册表名称
    "growl_sound": "minecraft:entity.wolf.growl",
    // 受伤时播放的声音事件的注册表名称
    "hurt_sound": "minecraft:entity.wolf.hurt",
    // 空闲时在生命值满的情况下,随机播放(1/3 的概率)的声音事件的注册表名称
    "pant_sound": "minecraft:entity.wolf.pant",
    // 空闲时在生命值未满的情况下,随机播放(1/3 的概率)的声音事件的注册表名称
    "whine_sound": "minecraft:entity.wolf.whine"
}

客户端资源

客户端文件中的原始 ResourceLocation(用于标识符或纹理)正在被定义标识符以及潜在纹理路径的对象所取代。有三个主要对象需要了解:ClientAssetModelAndTextureMaterialAssetGroup

ClientAsset 是一个 id/纹理对,用于指向纹理位置。默认情况下,纹理路径由 id 构造,路径以 textures 为前缀,并以 PNG 扩展名为后缀。

ModelAndTexture 是一个对象/客户端资源对,当渲染器应在多个模型之间选择时使用。通常,渲染器会创建一个对象类型到模型的映射,并提供给 ModelAndTexture 的对象用作映射中的查找键。

MaterialAssetGroup 是一个处理用某些纹饰材料渲染装备资源的处理器。它接受用于叠加到盔甲上的基础纹理,以及针对给定装备资源的任何覆盖。

  • net.minecraft.advancements.DisplayInfo 现在接受一个 ClientAsset 而不是仅一个 ResourceLocation 作为背景纹理
  • net.minecraft.client.model
    • AdultAndBabyModelPair - 保存两个 Model 实例,表示某个实体的成年和幼年形态。
    • ChickenModel#createBaseChickenModel - 创建默认的鸡模型。
    • ColdChickenModel - 寒冷温度下鸡的变体模型。
    • ColdCowModel - 寒冷温度下奶牛的变体模型。
    • ColdPigModel - 寒冷温度下猪的变体模型。
    • CowModel#createBaseCowModel - 创建奶牛的基础模型。
    • PigModel#createBasePigModel - 创建默认的猪模型。
    • WarmCowModel - 温暖温度下奶牛的变体模型。
  • net.minecraft.client.renderer.entity
    • ChickenRenderer 现在继承 MobRenderer 而不是 AgeableMobRenderer
    • CowRenderer 现在继承 MobRenderer 而不是 AgeableMobRenderer
    • PigRenderer 现在继承 MobRenderer 而不是 AgeableMobRenderer
  • net.minecraft.client.renderer.entity.layers.SheepWoolUndercoatLayer - 一个渲染绵羊羊毛底层的层。
  • net.minecraft.client.renderer.entity.state
    • CowRenderState - 奶牛实体的渲染状态。
    • SheepRenderState
      • getWoolColor - 返回绵羊羊毛的整数颜色。
      • isJebSheep - 返回绵羊的名称是否包含 jeb_ 前缀。
  • net.minecraft.core.ClientAsset - 一个包含标识符和指向某个纹理的路径的对象。
  • net.minecraft.data.loot.EntityLootSubProvider#killedByFrogVariant 现在接受 FrogVariantHolderGetter
  • net.minecraft.data.tags.CatVariantTagsProvider 类已移除
  • net.minecraft.tags.CatVariantTags 类已移除
  • net.minecraft.world.entity.animal
    • AbstractCow - 一个代表奶牛(牛)的抽象动物。
    • Chicken#setVariantgetVariant - 处理鸡的变体信息。
    • ChickenVariant - 一个定义给定鸡的通用可渲染信息和生物群系生成的类。
    • ChickenVariants - 保存所有原版鸡变体的键。
    • Cow 现在继承 AbstractCow
    • CowVariant - 一个定义给定奶牛的通用可渲染信息和生物群系生成的类。
    • CowVariants - 保存所有原版奶牛变体的键。
    • CatVariant(ResourceLocation) -> CatVariant(ClientAsset, SpawnPrioritySelectors)
    • CatVariants - 保存所有原版猫变体的键。
    • FrogVariant -> .frog.FrogVariant
      • FrogVariant(ResourceLocation) -> FrogVariant(ClientAsset, SpawnPrioritySelectors)
    • MushroomCow 现在继承 AbstractCow
    • PigVariant - 一个定义给定猪的通用可渲染信息和生物群系生成的类。
    • TemperatureVariants - 一个接口,保存指示不同温度下实体的 ResourceLocation
  • net.minecraft.world.entity.variant.ModelAndTexture - 定义带有其关联纹理的模型。
  • net.minecraft.world.item.equipment.trim
    • MaterialAssetGroup - 一个资源定义了一些基础以及基于所穿戴装备的排列。
    • TrimMaterial 现在接受 MaterialAssetGroup 而不是原始基础和覆盖

标签与解析

标签已被重写,移除了任何对类型的直接引用,同时密封并最终确定了相关类。从标签获取值现在返回一个 Optional 包装的条目,除非您调用 get*Or 方法之一,在其中指定默认值。另一方面,对象不接受默认值,而是返回所需标签的空变体。

// 对于某个 `CompoundTag` tag

// 读取一个值
Optional<Integer> value1 = tag.getInt("value1");
int value1Raw = tag.getIntOr("value1", 0);

// 读取另一个对象
Optional<CompoundTag> childTag = tag.getCompound("childTag");
CompoundTag childTagRaw = tag.getCopmoundOrEmpty("childTag");

使用编解码器写入

CompoundTag 现在有使用 CodecMapCodec 进行写入和读取的方法。对于 Codec,它将序列化的数据存储在指定的键内。对于 MapCodec,它将字段合并到顶层标签上。

// 对于某个 Codec<ExampleObject> CODEC 和 MapCodec<ExampleObject> MAP_CODEC
// 我们还有一个 ExampleObject example
CompoundTag tag = new CompoundTag();

// 对于编解码器
tag.store("example_key", CODEC, example);
Optional<ExampleObject> fromCodec = tag.read("example_key", CODEC);

// 对于映射编解码器
tag.store(MAP_CODEC, example);
Optional<ExampleObject> fromMapCodec = tag.read(MAP_CODEC);

命令解析器

packrat 解析器已更新了新的规则和系统,允许命令具有基于解析器的参数。这来自于 CommandArgumentParser,它解析某些语法以返回所需的对象。然后解析器被 ParserBasedArgument 使用,它尝试解析字符串并根据您当前键入的内容构建任何建议。这些都由 Grammar 类处理,它实现了 CommandArgumentParser,使用原子、字典、规则和术语的组合构建。

  • net.minecraft.commands.ParserUtils#parseJson
  • net.minecraft.commands.arguments
    • ComponentArgument 现在继承 ParserBasedArgument
    • NbtTagArgument 现在继承 ParserBasedArgument
    • StyleArgument 现在继承 ParserBasedArgument
  • net.minecraft.commands.arguments.item.ItemPredicateArgument 现在继承 ParserBasedArgument
  • net.minecraft.nbt
    • ByteArrayTag,现在是 final,不再接受列表对象
    • ByteTag 现在是一个记录
    • CollectionTag 现在是一个密封接口,不再继承 AbstractList 或具有泛型
      • setadd 已移除
      • remove 现在返回一个 Tag
      • get - 返回指定索引处的标签。
      • getElementType 已移除
      • size - 返回集合的大小。
      • isEmpty - 返回集合是否没有元素。
      • stream - 流式传输集合的元素。
    • CompoundTag 现在是 final
      • store - 将编解码器或映射编解码器写入标签。
      • read - 从标签中读取编解码器或映射编解码器编码的值。
      • getFloatOrDefaultgetIntOrDefaultgetLongOrDefault - 获取具有关联键的值,如果不存在或抛出异常则返回默认值。
      • storeNullable - 当不为 null 时,使用编解码器将值写入标签。
      • putUUIDgetUUIDhasUUID 已移除
      • getAllKeys -> keySet
      • valuesforEach - 实现标准的映射操作。
      • 接受列表对象的 putByteArrayputIntArray 已移除
      • getTagType 已移除
      • contains 已移除
      • get*get*Or - 返回键的可选包装对象,如果使用 Or 方法,则返回指定的默认值。
    • DoubleTag 现在是一个记录
    • EndTag 现在是一个记录
    • FloatTag 现在是一个记录
    • IntArrayTag,现在是 final,不再接受列表对象
    • IntTag 现在是一个记录
    • ListTag,现在是 final,继承 AbstractList
      • addAndUnwrap - 将标签添加到列表中,如果是一个包含单个元素的复合标签,则改为添加内部标签。
      • get*get*Or - 返回键的可选包装对象,如果使用 Or 方法,则返回指定的默认值。
      • compoundStream - 返回列表中所有 CompoundTag 的扁平映射。
    • LongArrayTag,现在是 final,不再接受列表对象
    • LongTag 现在是一个记录
    • NbtIo#readUnnamedTag 现在是公开的,用于测试
    • NbtOps 现在有一个私有构造函数
    • NbtUtils
      • getDataVersion 现在有一个接受 Dynamic 的重载
      • createUUIDloadUUID 已移除
      • readBlockPoswriteBlockPos 已移除
    • NumericTag 现在是一个实现 PrimitiveTag 的密封接口
      • getAsLong -> longValue
      • getAsInt -> intValue
      • getAsShort -> shortValue
      • getAsByte -> byteValue
      • getAsDouble -> doubleValue
      • getAsFloat -> floatValue
      • getAsNumber -> box
      • as* - 返回数值的可选包装。
    • PrimitiveTag - 一个密封接口,表示标签数据是一个原始对象。
    • ShortTag 现在是一个记录
    • SnbtGrammar - 用于字符串化 NBT 的解析器创建器。
    • SnbtOperations - 一个包含用于解析某些值的内置操作的辅助工具。
    • StringTag 现在是一个记录
    • StringTagVisitor
      • visit -> build,不是一对一
      • handleEscape -> handleKeyEscape,现在是私有的
    • Tag 现在是一个密封接口
      • as* -> 尝试将标签转换为其子类型之一,失败时返回空 optional。
      • getAsString -> asString,不是一对一
    • TagParser 现在持有一个泛型,引用要解析到的中间对象的类型
      • 构造函数现在接受一个语法,或者 createDynamicOps 构造语法
      • AS_CODEC -> FLATTENED_CODEC
      • parseTag -> parseCompoundFullyparseCompoundAsArgument
        • 其他方法如 parseFullyparseAsArgument 解析到某个中间对象
        • 这些都是实例方法
      • readKeyreadTypedValue 已移除
    • TagType#isValue 已移除
  • net.minecraft.util.parsing.packrat
    • CachedParseState - 一个缓存已解析位置并在读取时控制的解析状态。
    • Control#hasCut - 返回语法的控制流对于读取对象是否有 cut。
    • DelayedException - 一个创建要抛出的异常的接口。
    • Dictionary
      • put 现在返回一个 NamedRule
      • put(Atom<T>, Term<S>, Rule.RuleAction<S, T>) -> putComplex
      • get -> getOtThrow,不是一对一
      • forward - 获取或写入术语到字典。
      • namedWithAlias - 创建一个对命名原子或其别名的新引用。
    • ErrorCollector$Nop - 一个什么都不做的错误收集器。
    • NamedRule - 一个具有关联名称的规则。
    • ParseState 现在是一个接口
      • 缓存逻辑已移至 CachedParseState
      • scope - 返回解析对象内当前正在分析的范围。
      • parse 现在接受 NamedRule 而不是 Atom
      • acquireControlreleaseControl - 处理获取解析期间使用的 Control
      • silent - 返回一个不收集任何错误的 ParseState
    • Rule
      • parse$RuleAction#run 现在返回一个可为 null 的值,而不是 optional
      • SimpleRuleAction 现在实现 $RuleAction
    • Scope#pushFramepopFramesplitFrameclearFrameValuesmergeFrame - 处理将解析术语管理到称为帧的部分中。
    • Term
      • named -> Dictionary#named,不是一对一
      • repeatedrepeatedWithTrailingSeparatorrepeatedWithoutTrailingSeparator - 处理类似于 varargs 的重复术语,并将它们放入列表中。
      • positiveLookaheadnegativeLookahead - 处理基于后续内容匹配信息的术语。
      • fail - 将术语标记为解析期间失败。
  • net.minecraft.util.parsing.packrat.commands
    • CommandArgumentParser - 将字符串解析为与命令一起使用的参数。
    • Grammar 现在接受顶部的 NamedRule 而不是 Atom
    • GreedyPatternParseRule - 一个尝试贪婪匹配提供的模式的规则,假设如果某个区域匹配,则可以获得匹配的组。
    • GreedyPredicateParseRule - 一个尝试贪婪匹配接受的字符的规则,确保字符串达到最小大小。
    • NumberRunParseRule - 一个尝试从字符串解析数字的规则。
    • ParserBasedArgument - 一个使用解析器提取值的命令参数。
    • ResourceLookupRule 现在接受 id 解析器的 NamedRule 而不是 Atom
    • StringReaderParserState 现在继承 CachedParsedState
      • 不再接受 Dictoionary
    • StringReaderTerms#characters - 匹配字符串中的多个字符,通常用于捕获小写和大写变体。
    • UnquotedStringParseRule - 一个将序列的一部分作为未引用字符串读取的规则,确保它达到最小大小。

保存数据,现在带有类型

SavedData 已被重写,将其大部分保存和加载逻辑抽象到单独的 SavedDataType 中。这意味着 save 覆盖以及额外的 loadfactory 方法现在都在 SavedDataType 本身内部处理。

要构造一个 SavedDataType,您需要传入四个参数。首先是字符串标识符,用于解析保存您信息的 .dat 文件。这必须是一个有效的路径。然后是构造函数,当没有信息存在时,它接受 SavedData$Context 来返回您的数据对象的实例。接下来是编解码器,它接受 SavedData$Context 并返回一个用于读取和写入您的保存数据的 Codec。最后是用于数据修复器的 DataFixTypes。由于这是一个静态枚举,如果您计划使用原版数据修复器,您将需要注入到枚举本身中,或者修补 DimensionDataStorage#readTagFromDisk 中的 update 调用以传入 null 值。

// 我们的保存数据实例
public class ExampleSavedData extends SavedData {

    // 保存数据类型
    public static final SavedDataType<ExampleSavedData> TYPE = new SavedDataType<>(
        // 最好用您的模组 id 后跟下划线作为标识符的前缀
        // 斜杠会抛出错误,因为文件夹不存在
        // 将解析为 `saves/<world_name>/data/examplemod_example.dat`
        "examplemod_example",
        // 新实例的构造函数
        ExampleSavedData::new,
        // 用于编码和解码数据的编解码器工厂
        ctx -> RecordCodecBuilder.create(instance -> instance.group(
            RecordCodecBuilder.point(ctx.levelOrThrow()),
            Codec.INT.fieldOf("value1").forGetter(data -> data.value1),
            Codec.BOOL.fieldOf("value2").forGetter(data -> data.value2)
        ).apply(instance, ExampleSavedData::new));
    );

    private final ServerLevel level;
    private final int value1;
    private final boolean value2;


    // 用于新实例
    private ExampleSavedData(ServerLevel.Context ctx) {
        this(ctx.levelOrThrow(), 0, false);
    }

    // 用于编解码器
    // 如果不使用 `DimensionDataStorage#set`,构造函数不需要是公开的
    private ExampleSavedData(ServerLevel level, int value1, boolean value2) {
        this.level = level;
        this.value1 = value1;
        this.value2 = value2;
    }

    // 其他方法在此处
}

// 在可以访问 DimensionDataStorage storage 的地方
ExampleSavedData data = storage.computeIfAbsent(ExampleSavedData.TYPE);
  • net.minecraft.server.ServerScoreboard
    • dataFactory 已移除
    • createData 现在接受一个 $Packed 实例
  • net.minecraft.world.RandomSequences
    • factoryload 已移除
    • codec - 根据当前世界种子为随机序列构造一个编解码器。
  • net.minecraft.world.entity.raid.Raids 不再接受任何参数
    • getType - 根据当前维度返回保存数据类型。
    • factory 已移除
    • tick 现在接受 ServerLevel
    • getId - 获取突袭实例的标识符。
    • canJoinRaid 不再接受突袭实例
    • load 不再接受 ServerLevel
  • net.minecraft.world.level.levelgen.structure.structures.StructureFeatureIndexSavedData
    • factoryload 已移除
    • type - 返回具有指定 id 的要素保存数据类型。
  • net.minecraft.world.level.saveddata
    • SavedData
      • save 已移除
      • $Factory 记录已移除
      • $Context - 保存保存数据正在写入的当前上下文。
    • SavedDataType - 一个表示保存数据类型的记录,包括关于如何构造、保存和加载数据的信息。
  • net.minecraft.world.level.saveddata.maps
    • MapIndex 现在有一个接受最后一个地图 id 的构造函数
      • factoryload 已移除
      • getFreeAuxValueForMap -> getNextMapId
    • MapItemSavedData
      • factoryload 已移除
      • type - 使用地图 id 的键返回保存数据类型。
  • net.minecraft.world.level.storage.DimensionDataStorage 现在接受一个 SavedData$Context
    • computeIfAbsentget 现在只接受 SavedDataType
    • set 现在接受 SavedDataType 以及数据实例
  • net.minecraft.world.scores.ScoreboardSaveData
    • load -> loadFrom
    • pack - 将数据打包到其保存数据格式中。
    • $Packed - 表示可序列化的打包数据。

渲染管线重做

无论您之前使用的是着色器还是 RenderType,将对象渲染到屏幕的方式都已完全或部分重做。因此,很多事情需要重新解释,下面将进行更深入的探讨。然而,对于不关心细节的人,这里是 TL;DR。

首先,着色器 JSON 不再存在。这被 RenderPipeline 取代,它实际上是一个代码中的替代品。其次,RenderPipeline 强制将大多数任意值转换为对象。例如,您不再存储混合函数模式 id,而是存储一个 BlendFunction 对象。同样,您不再存储或设置直接的纹理对象,而是通过 GpuTexture 进行管理。最后,VertexBuffer 可以通过直接传入 RenderPipeline 并更新消费者中任何必要的统一变量来绘制到帧缓冲区,或者通过传入 RenderType 来绘制。

现在,对于需要细节的人,让我们深入探讨。

抽象化 Open GL

众所周知,Minecraft 一直在抽象化其 OpenGL 调用和常量,此版本也不例外。除 BufferUsage 外,所有对 GL 代码的调用都已移出对象引用,通常通过调用 GlConst$toGl 来获得。然而,随着所有其他渲染重做,有许多变化和复杂性需要学习一个全新的系统,假设您不使用 RenderType

从头开始,对底层渲染系统的所有调用都通过 GpuDevice,这是一个像 OpenGL 或 Vulkan 这样的渲染库的通用实现的接口。该设备负责创建缓冲区和纹理,执行任何所需的命令。可以通过 RenderSystem 通过 getDevice 获取当前的 GpuDevice,如下所示:

GpuDevice device = RenderSystem.getDevice();

然后,GpuDevice 可以分别使用 createBuffercreateTexture 创建带有所需数据的缓冲区或包含要渲染信息的纹理。为冗余起见,缓冲区保存顶点数据,而纹理保存纹理(颜色和深度)数据。您通常应缓存缓冲区或纹理对象以供以后使用,并根据需要更新任何附加数据。作为参考,缓冲区通常通过使用 BufferBuilderByteBufferBuilder 首先构建 MeshData,然后再将其传递给 createBuffer 来创建。

设置好所需的缓冲区和纹理后,我们如何实际修改将它们渲染到屏幕?这由 CommandEncoder 处理,它也可以通过 GpuDevice#createCommandEncoder 从设备获得。编码器包含熟悉的读写方法,以及一些额外的将纹理清除为给定颜色或直接将纹理 blit 到屏幕(presentTexture)的方法。然而,这里最重要的方法是 createRenderPass。它接受要绘制到屏幕的 GpuTexture 以及背景的默认 ARGB 颜色。此外,它还可以接受深度纹理。这应该使用 try-with-resources 块来创建,如下所示:

// 我们假设您已经构造了一个用于颜色数据的 `GpuTexture` texture
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(this.texture, OptionalInt.of(0xFFFFFFFF))) {
    // 在此处设置内容

}

RenderPass 内部,您可以设置要使用的 RenderPipeline,它定义了关联的着色器,绑定来自其他目标的任何采样器或设置统一变量,剪切屏幕的一部分以进行渲染,以及设置用于定义要渲染的顶点的顶点和索引缓冲区。最后,可以使用 draw 方法之一将所有内容绘制到屏幕上,提供起始索引和顶点计数。

// 如果缓冲区/纹理尚未创建或缓存,请在此处创建它们
// 在渲染通道打开时,不能运行来自 `CommandEncoder` 的任何方法
RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
GpuBuffer vertexBuffer = RenderSystem.getQuadVertexBuffer();
GpuBuffer indexBuffer = indices.getBuffer(6);

// 我们假设您已经构造了一个用于颜色数据的 `GpuTexture` texture
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(this.texture, OptionalInt.of(0xFFFFFFFF))) {

    // 设置管道信息以及任何采样器和统一变量
    pass.setPipeline(EXAMPLE_PIPELINE);
    pass.setVertexBuffer(0, vertexBuffer);
    pass.setIndexBuffer(indexBuffer, indices.type());
    pass.bindSampler("Sampler0", RenderSystem.getShaderTexture(0));

    // 然后,将所有内容绘制到屏幕
    // 在此示例中,缓冲区只包含一个四边形
    // 对于那些不知道的人来说,顶点计数为 6,因为四边形由 2 个三角形组成,所以有 2 个顶点重叠
    pass.drawIndexed(0, 6);
}

然而,除非您需要如此精细的控制,否则建议在必要时使用带有 MultiBufferSourceRenderType,因为它会为您设置大部分内容。

对象引用

大多数用于确定模式和处理纹理的 GL 代码的原始引用已被对象取代。正如 TL;DR 之前提到的,这些通常存储为某种枚举或对象,然后可以解析为其 GL 对应项。一些对象直接包含其引用标识符,例如 BlendFunction。其他对象只是占位符,在适当的位置解析,例如 DepthTestFunction,其枚举值通过 RenderPipeline#toGl 转换。

然而,最大的变化是增加了 GpuTexture。它负责管理与创建、写入和释放写入到某个缓冲区的纹理相关的任何事情。在初始化时,纹理被创建和绑定,并设置任何必要的参数用于 mipmap 和纹理格式。这些 GpuTexture 被存储和引用在任何地方,从 RenderTarget 的深度和颜色目标到支持 TextureAtlas 的纹理。然后,一旦不再需要,纹理通过调用 #close 释放。请注意,尽管技术上可以再次调用 #bind,但纹理已被视为删除,不应再使用。

如果由于某种原因,您需要使用 GpuTexture,实际上使用起来非常简单。首先,您只需通过 GpuDevice#createTexture 构造 GpuTexture。然后,如果您需要更改任何寻址或纹理 mipmap 过滤器,您可以在写入之前随时应用它们。

public class MyTextureManager {
    
    private final GpuTexture texture;

    public MyTextureManager() {
        this.texture = RenderSystem.getDevice().createTexture(
            // 纹理名称,用于日志记录和调试
            "Example Texture",
            // 纹理像素的格式,可以是三个值之一:
            // 值:   (纹理内部格式, 纹素数据格式,   纹素数据类型,     像素大小)
            // - RGBA8   (GL_RGBA8,                GL_RGBA,            GL_UNSIGNED_BYTE, 4)
            // - RED8    (GL_R8,                   GL_RED,             GL_UNSIGNED_BYTE, 1)
            // - DEPTH32 (GL_DEPTH_COMPONENT32,    GL_DEPTH_COMPONENT, GL_FLOAT,         4)
            TextureFormat.RGBA8,
            // 纹理宽度
            16,
            // 纹理高度
            16,
            // mipmap 级别和最大细节级别(最小为 1)
            1
        );

        // 设置 UV 分量的纹理模式
        // 值:
        // - REPEAT        (GL_REPEAT)
        // - CLAMP_TO_EDGE (GL_CLAMP_TO_EDGE)
        this.texture.setAddressMode(
            // 用于 U 分量的模式 (GL_TEXTURE_WRAP_S)
            AddressMode.CLAMP_TO_EDGE,
            // 用于 V 分量的模式 (GL_TEXTURE_WRAP_R)
            AddressMode.REPEAT
        );

        // 设置用于在屏幕上缩放纹理的过滤函数
        // 值    (默认,    用于 mipmap):
        // - NEAREST (GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR)
        // - LINEAR  (GL_LINEAR,  GL_LINEAR_MIPMAP_LINEAR)
        this.texture.setTextureFilter(
            // 用于纹理缩小函数的模式 (GL_TEXTURE_MIN_FILTER)
            FilterMode.LINEAR,
            // 用于纹理放大函数的模式 (GL_TEXTURE_MAG_FILTER)
            FilterMode.NEAREST,
            // 是否应为缩小函数使用 mipmap(当为 true 时,应具有高于 1 的 mipmap 级别)
            false
        );
    }
}

然后,每当您想要将某些内容上传到纹理时,您可以调用 CommandEncoder#writeToTextureCommandEncoder#copyTextureToTexture。这要么接受要写入的 NativeImage,要么接受带有纹理数据和要使用的 NativeImage$FormatIntBuffer

// 像其他缓冲区/纹理修改方法一样,这必须在渲染通道之外完成
// 我们假设您有一些要加载到纹理中的 `NativeImage` image
RenderSystem.getDevice().createCommandEncoder().writeToTexture(
    // 正在写入的纹理(目标)
    this.texture,
    // 正在读取的图像(源)
    image,
    // mipmap 级别
    0,
    // 起始目标 x 偏移
    0,
    // 起始目标 y 偏移
    0,
    // 目标宽度(x 大小)
    16,
    // 目标高度(y 大小)
    16,
    // 起始源 x 偏移
    0,
    // 起始源 y 偏移
    0
)

最后,当您使用完纹理后,如果它没有被自动处理,不要忘记通过 #close 释放它。

渲染管线

以前,管道是使用 JSON 构造的,其中包含从顶点和片段着色器到其定义的值、采样器和统一变量的所有元数据。然而,这已被一个代码内解决方案取代,该方案将 JSON 的某些部分和原本归入 RenderType 的部分更加本地化。这被称为 RenderPipeline

可以使用其构建器通过 RenderPipeline#builder 构造 RenderPipeline。然后可以通过调用 build 来构建管道。如果您希望着色器无需任何额外工作即可预编译,则可以将最终的管道传递给 RenderPipeline#register。但是,如果您希望更优雅地处理失败状态,也可以自己处理编译。如果您有跨多个管道使用的代码片段,则可以构建一个部分管道(通过 $Builder#buildSnippet),然后在 builder 方法中将其传递给构造管道。

示例中描述的以下枚举已提供其 GL 代码,因为它们已被抽象化。

// 这假设 RenderPipeline#register 已通过某种形式变为公开
public static final RenderPipeline EXAMPLE_PIPELINE = RenderPipelines.register(
    RenderPipeline.builder()
    // 管道的名称(必需)
    .withLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "pipeline/example"))
    // 顶点着色器的位置,相对于 'shaders'(必需)
    // 指向 'assets/examplemod/shaders/example.vsh'
    .withVertexShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
    // 片段着色器的位置,相对于 'shaders'(必需)
    // 指向 'assets/examplemod/shaders/example.fsh'
    .withFragmentShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
    // 着色器内顶点的格式(必需)
    .withVertexFormat(
        // 顶点格式
        DefaultVertexFormat.POSITION_TEX_COLOR,
        // 格式的模式
        VertexFormat.Mode.QUADS
    )
    // 添加可以在着色器中引用的常量
    // 可以指定名称以及一个 int / float 来表示其值
    // 如果未指定值,则应使用 #ifdef / #endif 块进行门控
    .withShaderDefines("ALPHA_CUTOUT", 0.5)
    // 添加可以在着色器中引用的纹理 sampler2D
    // 通常,存储在 `RenderSystem` 中的着色器纹理通过 `Sampler0` - `Sampler11` 引用
    // - `Sampler0` 通常总是存在,但这些应该事先设置好
    // 此外,对于渲染目标,`InSampler` 通常存在,以及在后处理通道中定义的任何采样器
    .withSampler("Sampler0")
    // 添加可以在着色器中引用的统一变量
    // 这些只是定义,然后根据情况由调用者填充或默认填充
    // 默认值可以在 `CompiledShaderProgram#setupUniforms` 中找到
    .withUniform("ModelOffset", UniformType.VEC3)
    // 自定义统一变量必须手动设置,因为原版批处理系统不支持这样的操作
    .withUniform("CustomUniform", UniformType.INT)
    // 设置用于在离相机不同距离处渲染对象的深度测试函数
    // 值:
    // - NO_DEPTH_TEST      (GL_ALWAYS)
    // - EQUAL_DEPTH_TEST   (GL_EQUAL)
    // - LEQUAL_DEPTH_TEST  (GL_LEQUAL)
    // - LESS_DEPTH_TEST    (GL_LESS)
    // - GREATER_DEPTH_TEST (GL_GREATER)
    .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST)
    // 设置多边形应如何渲染
    // 值:
    // - FILL      (GL_FILL)
    // - WIREFRAME (GL_LINE)
    .withPolygonMode(PolygonMode.FILL)
    // 当为 true 时,可以剔除正面或背面的多边形
    .withCull(false)
    // 指定将两个带有 alpha 的颜色混合在一起时要使用的函数
    // 由 `GlStateManager$SourceFactor` 和 `GlStateManager$DestFactor` 组成
    // 前两个用于 RGB,后两个用于 alpha
    // 如果未指定任何内容,则禁用混合
    .withBlend(BlendFunction.TRANSLUCENT)
    // 决定是否屏蔽写入颜色和 alpha 到绘制缓冲区
    .withColorWrite(
        // 屏蔽 RGB
        false,
        // 屏蔽 alpha
        false
    )
    // 决定是否屏蔽写入值到深度缓冲区
    .withDepthWrite(false)
    // 决定将 RGBA 颜色应用到帧缓冲区时要应用的逻辑操作
    .withColorLogic(LogicOp.NONE)
    // 设置用于计算多边形深度值的比例和单位。
    // 这取代了多边形偏移。
    .withDepthBias(0f, 0f)
    .build()
);

从那里,管道可以直接使用,也可以通过某些 RenderType 使用:

// 这将假设 RenderType#create 是公开的
public static final RenderType EXAMPLE_RENDER_TYPE = RenderType.create(
    // 渲染类型的名称
    "examplemod:example",
    // 缓冲区的大小
    // 或 4MB
    4194304,
    // 是否影响应用于方块实体的破碎效果
    false,
    // 顶点在上传前是否应排序
    true,
    // 要使用的管道
    EXAMPLE_PIPIELINE,
    // 要应用的任何其他复合状态设置
    RenderType.CompositeState.builder().createCompositeState(RenderType.OutlineProperty.NONE)
);

然后可以通过创建 RenderPass 并将 RenderPipeline 设置为使用您的管道来绘制管道。对于 RenderType,可以使用 MultiBufferSource#getBuffer 获得关联的缓冲区。请注意,不应在 RenderType 中使用自定义统一变量,因为它们不容易设置。

// 由于我们使用的是自定义统一变量,我们必须自己处理
// 我们假设我们有某个 `GpuTexture` texture 要写入

// 创建要使用的渲染通道
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(
        // 要写入的 GPU 颜色纹理
        this.texture,
        // ARGB 格式的清除颜色
        OptionalInt.of(0xFFFFFFFF),
        // 深度纹理和清除深度值也可以在此处构造
    )
) {
    // 添加管道和我们的统一变量
    pass.setPipeline(EXAMPLE_PIPELINE);
    pass.setUniform("CustomUniform", 1);
    
    // 设置任何其他采样器和要使用的顶点/索引缓冲区

    // 最后,调用 draw 函数之一
    // 接受要绘制的顶点的第一个索引和索引计数
    pass.draw(...);
}

后处理效果

鉴于管道 JSON 已被剥离,这也影响了后处理效果。program 被直接指定 vertex_shaderfragment_shader 所取代。此外,统一变量必须指定其 type

// 1.21.5 之前(对于 'passes' 中的某个 pass)
{
    // 与之前相同
    "inputs": [ /*...*/ ],
    "output": "swap",

    // 被 'vertex_shader', 'fragment_shader' 取代
    "program": "minecraft:post/box_blur",

    "uniforms": [
        {
            "name": "BlurDir",
            // 必需
            "values": [ 1.0, 0.0 ]
        },
        {
            "name": "Radius",
            // 必需
            "values": [ 0.0 ]
        }
    ]
}

// 1.21.5(对于 'passes' 中的某个 pass)
{
    // 与之前相同
    "inputs": [ /*...*/ ],
    "output": "swap",

    // 相对于 'shaders'
    // 指向 'assets/minecraft/shaders/post/blur.vsh'
    "vertex_shader": "minecraft:post/blur",
    // 指向 'assets/minecraft/shaders/post/box_blur.fsh'
    "fragment_shader": "minecraft:post/box_blur",


    "uniforms": [
        {
            "name": "BlurDir",
            // 指定为此统一变量使用的类型
            // `Uniform$Type` 之一:
            // - int
            // - ivec3
            // - float
            // - vec2
            // - vec3
            // - vec4
            // - matrix4x4
            "type": "vec2",
            "values": [ 1.0, 0.0 ]
        },
        {
            "name": "Radius",
            "type": "float"
            // values 不再是必需的
        }
    ]
}

请注意,如果您没有为统一变量定义值,则必须在处理 PostChain 之前在 PostChain#processRenderPass 消费者中通过调用 #setUniform 来指定它们。

// 假设我们已经得到了 `PostChain` post
post.process(Minecraft.getInstance().getMainRenderTarget(), GraphicsResourceAllocator.UNPOOLED, pass -> {
    pass.setUniform("Radius", 0.4f);
});
  • com.mojang.blaze3d.GpuOutOfMemoryException - 当无法在 GPU 上分配纹理时抛出的异常。
  • com.mojang.blaze3d.buffers
    • BufferType 不再存储 GL 代码,现在在 GlConst#toGl
    • BufferUsage 不再存储 GL 代码,现在在 GlConst#toGl
      • isReadableisWritable - 返回缓冲区是否可读或可写。
    • GpuBuffer 现在是抽象的
      • 带有 ByteBuffer 的构造函数已移除
      • size - 返回缓冲区的大小。
      • type - 返回缓冲区的类型。
      • resizewritereadbind 已移除
      • usage - 返回缓冲区的用途。
      • close 现在是抽象的
      • isClosed - 返回缓冲区是否已关闭。
      • $ReadView 现在是一个接口,定义了缓冲区数据以及如何关闭视图
  • com.mojang.blaze3d.font.SheetGlyphInfo#upload 现在接受一个 GpuTexture
  • com.mojang.blaze3d.opengl
    • DirectStateAccess - 一个创建数据并将其绑定到某个帧缓冲区的接口。
      • $Core - 一种修改帧缓冲区而不将其绑定到上下文的 DSA 实现。
      • $Emulated - 一种仍然绑定上下文的 DSA 抽象。
    • GlBuffer - 用于 OpenGL 的 GpuBuffer 实现。
    • GlCommandEncoder - 用于 OpenGL 的 CommandEncoder 实现。
    • GlDebugLabel - 用于处理对 GL 指定数据结构的调试引用的标签器。
    • GlDevice - 用于 OpenGL 的 GpuDevice 实现。
    • GlRenderPass - 用于 OpenGL 的 RenderPass 实现。
    • GlRenderPipeline - 用于 OpenGL 的 CompiledRenderPipeline 实现。
    • GlTexture - 用于 OpenGL 的 GpuTexture 实现。
    • VertexArrayCache - 用于绑定顶点数组并将其上传到 OpenGL 管道的缓存。
  • com.mojang.blaze3d.pipeline
    • BlendFunction - 一个类,包含在目标中叠加像素时要应用的源和目标颜色及 alpha。这也包含所有原版混合函数。
    • CompiledRenderPipeline - 一个接口,包含具有渲染到屏幕所需所有信息的管道。
    • RenderPipeline - 一个类,包含将某个对象渲染到屏幕所需的一切。它在应用之前类似于渲染状态。
    • RenderTarget 现在接受一个表示目标名称的字符串
      • colorTextureId -> colorTexture,现在是一个 GpuTexture
        • 同样 getColorTextureId -> getColorTexture
      • depthBufferId -> depthTexture,现在是一个 GpuTexture
        • 同样 getDepthTextureId -> getDepthTexture
      • filterMode 现在是一个 FilterMode
        • 同样 setFilterMode 用于 int 参数
      • blitAndBlendToScreen 不再接受视口大小参数
      • framebufferId 已移除
      • checkStatus 已移除
      • bindWriteunbindWritesetClearColor 已移除
      • blitToScreen 不再接受任何参数
      • blitAndBlendToScreen -> blitAndBlendToTexture,不是一对一
      • clear 已移除
      • unbindRead 已移除
  • com.mojang.blaze3d.platform
    • DepthTestFunction - 一个枚举,表示在将样本渲染到帧缓冲区时要应用的受支持深度测试。
    • DisplayData 现在是一个记录
      • withSize - 创建一个具有指定宽度/高度的新实例。
      • withFullscreen - 创建一个具有指定全屏标志的新实例。
    • FramerateLimitTracker
      • getThrottleReason - 返回游戏帧率被限制的原因。
      • isHeavilyThrottled - 返回当前限制是否显著影响游戏速度。
      • $FramerateThrottleReason - 帧率被限制的原因。
    • GlConst -> com.mojang.blaze3d.opengl.GlConst
      • #toGl - 将某个引用对象映射到其关联的 OpenGL 代码。
    • GlDebug -> com.mojang.blaze3d.opengl.GlDebug
      • enableDebugCallback 现在接受一组启用的扩展。
    • GlStateManager -> com.mojang.blaze3d.opengl.GlStateManager
      • _blendFunc_blendEquation 已移除
      • _glUniform2(int, IntBuffer)_glUniform4(int, IntBuffer) 已移除
      • _glUniformMatrix2(int, boolean, FloatBuffer)_glUniformMatrix3(int, boolean, FloatBuffer) 已移除
      • _glUniformMatrix4(int, boolean, FloatBuffer) -> _glUniformMatrix4(int, FloatBuffer),transpose 现在始终为 false
      • _glGetAttribLocation 已移除
      • _glMapBuffer 已移除
      • _glCopyTexSubImage2D 已移除
      • _glBindRenderbuffer_glDeleteRenderbuffers 已移除
      • glGenRenderbuffers_glRenderbufferStorage_glFramebufferRenderbuffer 已移除
      • _texParameter(int, int, float) 已移除
      • _genTextures_deleteTextures 已移除
      • _texSubImage2D 现在有一个接受 IntBuffer 而不是 long 作为像素数据的重载
      • upload 已移除
      • _stencilFunc_stencilMask_stencilOp_clearStencil 已移除
      • _getTexImage 已移除
      • _glDrawPixels_readPixels 已移除
      • $CullState#mode 已移除
      • $DestFactor -> DestFactor,代码已移除,通过 GlConst#toGl 调用
      • $FramebufferState 枚举已移除
      • $LogicOp -> LogicOp,代码已移除,通过 GlConst#toGl 调用
        • OR_REVERSE 外,所有都已移除
        • NONE - 不执行逻辑操作。
      • $PolygonOffsetState#line 已移除
      • $SourceFactor -> SourceFactor,代码已移除,通过 GlConst#toGl 调用
      • $StencilFunc$StencilState 类已移除
      • $Viewport 枚举已移除
    • GlUtil 类已移除
      • getVendorgetRenderergetOpenGlVersion(现在为 getVersion)已移至 GpuDevice 上的实例抽象方法
      • getCpuInfo -> GLX#_getCpuInfo
    • GLX
      • getOpenGLVersionString 已移除
      • _init -> _getCpuInfo,不是一对一
      • _renderCrosshaircom.mojang.blaze3d.systems.RenderSystem#renderCrosshair -> net.minecraft.client.gui.components.DebugScreenOverlay#render3dCrosshair,不是一对一
    • PolygonMode - 一个枚举,定义多边形在缓冲区中将如何渲染。
    • NativeImage 构造函数现在是公开的
      • upload 已移除
      • getPointer - 返回指向图像数据的指针。
      • setPixelABGR 现在是公开的
      • applyToAllPixels 已移除
      • downloadTexturedownloadDepthBuffer 已移除
      • flipY 已移除
      • setPackPixelStoreStatesetUnpackPixelStoreState 已移除
      • $InternalGlFormat 枚举已移除
      • $Format 不再包含 GL 代码,现在在 GlConst#toGl
    • TextureUtil
      • generateTextureIdreleaseTextureId 已移除
      • prepareImage 已移除
      • writeAsPNG 现在接受一个 GpuTexture 而不是直接的三个整数
        • 没有 IntUnaryOperator 的重载已移除
  • com.mojang.blaze3d.resource
    • RenderTargetDescriptor 现在接受一个表示要清除到的颜色的整数
    • ResourceDescriptor
      • prepare - 在分配后准备资源以供使用。
      • canUsePhysicalResource - 通常返回一个描述符是否已经分配了相同的信息。
  • com.mojang.blaze3d.shaders
    • AbstractUniform -> com.mojang.blaze3d.opengl.AbstractUniform
      • setSafe 方法已移除
      • setMat* 方法已移除
      • set(Matrix3f) 已移除
    • CompiledShader -> com.mojang.blaze3d.opengl.GlShaderModule
      • $Type -> com.mojang.blaze3d.shaders.ShaderType
    • Uniform -> com.mojang.blaze3d.opengl.Uniform
      • 构造函数现在接受一个 $Type 而不是计数和一个表示类型的整数
      • UT_* 字段已移除
      • setFromConfig(ShaderProgramConfig.Uniform) 已移除
      • getTypeFromString 已移除
      • getType 现在返回一个 $Type
      • set(int, float) 已移除
      • setSafe 现在是私有的
      • $Type - 保存类型名称以及它包含多少个值。
      • getLocation 已移除
      • getCount -> $Type#count
      • getIntBuffergetFloatBuffer 已移除
      • $Type -> com.mojang.blaze3d.shaders.UniformType
  • com.mojang.blaze3d.systems
    • CommandEncoder - 一个接口,定义如何将各种命令编码到底层渲染系统,例如创建通道、清除和写入纹理,或从缓冲区读取。
    • GpuDevice - 一个接口,定义用于绘制到屏幕的设备或底层渲染系统。它负责创建缓冲区和纹理,同时编译任何管道。
    • RenderPass - 一个接口,定义如何使用底层渲染系统将给定的通道渲染到某个缓冲区。这允许绑定任何采样器并设置所需的统一变量。
    • RenderSystem
      • isOnRenderThreadOrInitassertOnRenderThreadOrInit 已移除
      • recordRenderCallreplayQueue 已移除
      • blendFuncblendFuncSeparateblendEquation 已移除
      • texParameterdeleteTexturebindTextureForSetup 已移除
      • stencilFuncstencilMaskstencilOp 已移除
      • clearDepth 已移除
      • glBindBufferglBindVertexArrayglBufferDataglDeleteBuffers 已移除
      • glUniform1i 已移除
      • glUniform1glUniform2glUniform3glUniform4 已移除
      • glUniformMatrix2glUniformMatrix3glUniformMatrix4 已移除
      • setupOverlayColor 现在接受一个 GpuTexture 而不是两个 int
      • beginInitializationfinishInitialization 已移除
      • renderThreadTesselator 已移除
      • setShaderclearShadergetShader 已移除
      • setShaderTexture 现在接受一个 GpuTexture 而不是一个绑定地址
      • getShaderTexture 现在返回一个 GpuTexture,如果不存在则返回 null
      • pixelStorereadPixels 已移除
      • queueFencedTaskexecutePendingTasks - 处理发送在 GPU 上异步运行的任务。
      • SCISSOR_STATE - 保存主要的剪裁状态。
      • disableDepthTestenableDepthTest 已移除
      • depthFuncdepthMask 已移除
      • enableBlenddisableBlend 已移除
      • neableCulldisableCull 已移除
      • polygonModeenablePolygonOffsetdisablePolygonOffsetpolygonOffset 已移除
      • enableColorLogicOpdisableColorLogicOplogicOp 已移除
      • bindTextureviewport 已移除
      • colorMaskclearColorclear 已移除
      • setupShaderLights(CompiledShaderProgram) 已移除
      • getShaderLights - 返回表示块光和天空光的向量。
      • drawElementsgetString 已移除
      • initRenderer 现在接受窗口指针、默认着色器源以及一个是否使用调试标签的布尔值
      • setupDefaultState 不再接受任何参数
      • maxSupportTextureSize 已移除
      • glDeleteVertexArrays 已移除
      • defaultBlendFunc 已移除
      • setShaderTexture 已移除
      • getQuadVertexBuffer - 返回一个绑定了一个四边形的顶点缓冲区。
      • getDevicetryGetDevice - 返回表示要使用的底层渲染系统的 GpuDevice
      • getCapsString 已移除
      • activeTexture 已移除
      • setModelOffsetresetModelOffsetgetModelOffset - 处理在渲染模型时应用于 ModelOffset 统一变量的偏移量。通常用于云和世界边界。
      • $AutoStorageIndexBuffer#bind -> getBuffer,不是一对一
      • $GpuAsyncTask - 一个保存回调和围栏对象的记录,用于将信息同步到 GPU。
    • ScissorState - 一个类,保存要渲染的屏幕部分。
  • com.mojang.blaze3d.textures
    • AddressMode - 设置为如何将纹理渲染到特定位置的模式。
    • FilterMode - 设置为当细节级别函数确定纹理应如何最大化或最小化时如何渲染纹理的模式。
    • GpuTexture - 根据需要绑定和写入 GPU 的纹理。
    • TextureFormat - 指定纹理应分配的格式。
  • com.mojang.blaze3d.vertex
    • PoseStack
      • mulPose(Quaternionf)rotateAround 现在接受 Quaternionfc 而不是 Quaternionf
      • clear -> isEmpty
      • mulPose(Matrix4f) -> mulPose(Matrix4fc)
      • $Pose
        • computeNormalMatrix 现在是私有的
        • transformNormal 现在接受 Vector3fc 作为其第一个参数
        • translatescalerotaterotateAroundsetIdentitymulPose 现在除了在堆栈上之外,在姿势本身上也可用
    • VertexBuffer -> com.mojang.blaze3d.buffers.GpuBuffer,不是一对一
      • 一些逻辑也移至 VertexFormat
    • VertexFormat
      • bindAttributes 已移除
      • setupBufferStateclearBufferStategetImmediateDrawVertexBuffer -> uploadImmediateVertexBufferuploadImmediateIndexBuffer;不是一对一
      • $IndexType 不再存储 GL 代码,现在在 GlConst#toGl
      • $Mode 不再存储 GL 代码,现在在 GlConst#toGl
    • VertexFormatElement
      • setupBufferState 已移除
      • $Type 不再存储 GL 代码,现在在 GlConst#toGl
      • $Usage 不再存储 GL 函数调用,现在在 VertexArrayCache#setupCombinedAttributes
  • com.mojang.math
    • MatrixUtil
      • isIdentityisPureTranslationisOrthonormal 现在接受一个 Matrix4fc
      • checkProperty - 检查提供的属性是否在矩阵中表示。
    • OctahedralGroup
      • transformation 现在返回一个 Matrix3fc
      • fromAnges -> fromXYAngles,不是一对一
    • Quadrant - 一个包含 90 度增量旋转的枚举。
    • SymmetricGroup3#transformation 现在返回一个 Matrix3fc
    • Transformation 现在接受一个 Matrix4fc
      • getMatrix 现在返回一个 Matrix4fc
      • getMatrixCopy - 返回当前矩阵的深拷贝。
  • net.minecraft.client.gui.font.FontTexture 现在接受一个提供的标签字符串
  • net.minecraft.client.main.GameConfig 现在接受一个布尔值,表示是否渲染调试标签
  • net.minecraft.client.renderer
    • CloudRenderer#render 不再接受用于投影或姿势的 Matrix4f
    • CompiledShaderProgram -> com.mojang.blaze3d.opengl.GlProgram
      • link 现在接受一个字符串作为着色器名称
      • setupUniforms 现在接受 $UniformDescription 列表以及采样器使用的名称列表
      • getUniformConfig 已移除
      • bindSampler 现在接受一个 GpuTexture 而不是整数绑定标识符
      • parseUniformNode 已移除
    • CoreShaders -> RenderPipelines,不是一对一
    • LightTexture#getTarget - 返回包含基于玩家的当前等级的光照纹理的 GpuTexture
    • PostChain
      • load 不再接受 ShaderManager,现在接受一个表示链名称的 ResourceLocation
      • addToFrameprocess 现在接受一个 RenderPass 消费者,用于将任何其他设置应用于要渲染的通道
      • setUniform 已移除
      • setOnRenderPass - 在 RenderPass 上的后处理链中设置统一变量,以供着色器使用。
    • PostChainConfig
      • $Pass 现在接受顶点和片段着色器的 id,而不是程序 id
        • referencedTargets - 返回通道中引用的要应用的目标。
        • program 已移除
      • $Uniform 现在接受统一变量的类型以及一个可选的浮点数列表(如果值不需要被覆盖)
    • PostPass 不再接受 CompiledShaderProgram,现在接受 RenderPipeline 而不是表示通道名称的字符串
      • addToFrame 现在接受一个 RenderPass 消费者,用于将任何其他设置应用于要渲染的通道
      • getShader 已移除
      • $Input#bindTo 现在接受 RenderPass 而不是 CompiledShaderProgram
    • RenderStateShard
      • 使用多边形偏移的 $LayerStateShard 已移除
      • getName - 返回着色器的名称。
      • $TransparencyStateShard 类已移除
        • 现在通过 BlendFunction 处理
      • $ShaderStateShard 类已移除
        • VertexBuffer 直接引用
      • $CullStateShard 类已移除
        • 现在作为 RenderPipeline 上的设置处理
      • $DepthTestStateShard 类已移除
        • 现在通过 DepthTestFunction 处理
      • $WriteMaskStateShard 类已移除
        • 现在作为 RenderPipeline 上的设置处理
      • $ColorLogicStateShard 类已移除
        • 现在作为 RenderPipeline 上的设置处理
      • $OutputStateShard 现在接受一个提供的 RenderTarget 而不是用于启动和拆除状态的 runnable
    • RenderType 不再接受 VertexFormatVertexFormat$Mode
      • SKYEND_SKYskyendSkystars 已移除
      • ENTITY_OUTLINE_BLITentityOutlineBlit 已移除
      • PANORAMApanorama 已移除
      • CREATE_LIGHTMAPcreateLightmap 已移除
      • createCloudsflatCloudscloudscloudsDepthOnly 已移除
      • worldBorder 已移除
      • debugLine - 返回与调试线关联的 RenderType
      • entityOutlineBlit - 返回用于渲染实体轮廓的 RenderType
      • panorama - 返回用于渲染全景模式的 RenderType
      • createLightmap - 返回用于渲染光照图纹理的 RenderType
      • create 不再接受 VertexFormatVertexFormat$Mode,而是接受 RenderPipeline
      • getRenderTargetgetRenderPipeline - 返回用于渲染的目标和管道。
      • formatmodedraw 现在是抽象的
      • $CompositeStateBuilder 方法现在是 protected
      • $OutlineProperty 现在是 protected
    • ShaderDefines$Builder#define 现在有一个接受整数的重载
    • ShaderManager
      • SHADER_INCLUDE_PATH 现在是私有的
      • MAX_LOG_LENGTH 已移除
      • preloadForStartup 已移除,被 GpuDevice#precompilePipeline 取代
      • getProgramgetProgramForLoading -> getShader,不是一对一
      • linkProgram 现在接受 RenderPipeline 而不是 ShaderProgramShaderProgramConfig
      • $CompilationCache#getOrCompileProgramgetOrCompileShader -> getShaderSource,不是一对一
      • $Configs 不再接受程序映射
      • $ShaderCompilationKey 记录已移除
    • ShaderProgramShaderProgramConfig -> RenderPipeline,不是一对一
    • SkyRenderer#renderDarkDisc 不再接受 PoseStack
  • net.minecraft.client.renderer.chunk.SectionRenderDispatcher
    • uploadSectionLayeruploadSectionIndexBuffer -> $RenderSection#uploadSectionLayeruploadSectionIndexBuffer
    • $SectionBuffers - 一个保存用于渲染部分的缓冲区的类。
  • net.minecraft.client.renderer.texture
    • AbstractTexture
      • NOT_ASSIGNED 已移除
      • texturegetTexture - 保存要渲染的纹理的引用。
      • getIdreleaseId 已移除
      • bind 已移除
    • DynamicTexture 现在接受纹理的标签
    • SpriteContents#uploadFirstFrame$AnimatedTexture#uploadFirstFrame 现在接受一个 GpuTexture
    • SpriteTicker#tickAndUpload 现在接受 GpuTexture
    • TextureAtlasSprite#uploadFirstFrame$Ticker#tickAndUpload 现在接受 GpuTexture

模型重做

模型系统已进一步分离为用于方块状态、方块和物品的模型。因此,统一的 BakedModel 已被完全移除,并分离到它们自己的部分中,分三步加载:从 JSON 加载、解析依赖关系,然后烘焙以供关联的方块状态模型或物品模型使用。作为参考,下面讨论的所有内容都是在 ModelManager#reload 中并行发生的。

首先,让我们从方块和物品之间使用的基础模型 JSON 开始。这些被加载到 UnbakedModel(具体来说是 BlockModel)中,其中包含熟悉的属性,例如 gui 光照和纹理槽位。然而,一个变化是将元素与其渲染设置分离。这些持有渲染四边形的元素存储在 UnbakedGeometry 中。UnbakedGeometry 负责将模型烘焙成 QuadCollection,它实际上保存了要渲染的 BakedQuad 列表。目前,原版只有 SimpleUnbakedGeometry,它保存了熟悉的 BlockElement 列表。这些 UnbakedModel 一旦加载,就会被传递给 ModelDiscovery 以解析方块状态和物品模型。

接下来是 ResolvableModel,它是方块状态和物品模型的基础。这些模型本质上作为标记,请求它们将使用的 UnbakedModel。然后,我们有它们的子类型 BlockStateModel$UnbakedRoot(用于方块状态 JSON)和 ItemModel$Unbaked(用于客户端物品 JSON 中引用的模型)。每个都以某种方式实现 resolveDependencies,以调用 ResolvableModel$Resolver#markDependency,传入它们想要使用的模型位置。

从技术上讲,BlockStateModel 更复杂一些,因为变体在加载期间使用 BlockStateModel$Unbaked,然后在初始化期间转换为 $UnbakedRoot

现在我们知道了应该加载哪些模型,它们必须被放入一个可用于烘焙的状态。这是 ModelDiscovery 的工作,它接受一个 ResolvableModel,并在第一次引用时将 UnbakedModel 加载到 ResolvedModel 中。顾名思义,ResolvedModel 是围绕 UnbakedModel 的功能包装器,用于解析所有依赖链。

从那里,为 BlockState 构建模型组,并加载纹理,从而进入实际烘焙 BlockStateModelItemModel 的最后一步。这通过 $UnbakedRoot(或 $Unbaked)和 ModelBakery 上提供的 bake 方法处理。简而言之,bake 构建 BakedQuad 列表,其中包含方块状态或物品模型本身所需的任何其他信息。ResolvedModel 从烘焙器中获得,然后调用其实例方法。对于 BlockStateModel,这通过 SimpleModelWrapper#bake 解析,从中从 Variant 数据获得 ModelState。它们将烘焙的四边形存储在 BlockModelPart 中。对于 ItemModel,它直接使用 BakedQuad 列表以及由 ModelRenderProperties#fromResolvedModel 提供的信息。这确实意味着每个 BlockStateModelItemModel 如果同一个模型在多个位置被引用,则可能包含重复(但唯一)的 BakedQuad

方块生成器:变体修改器

鉴于所有分离出方块状态 JSON 加载的变化,BlockModelGenerators 也有许多变化。虽然其中大部分只是重命名(例如,BlockStateGenerator -> BlockModelDefinitionGenerator),但主要变化是增加了 VariantMutatorVariantMutator 在功能上是 Variant 上的一元运算符,用于设置某些设置。这一增加简化了(或者说更像是编解码器构造)PropertyDispatch 的使用,以便更快速地根据其属性分派具有变体的方块。

// 在水平朝向属性上创建一个属性分派
// 应用关联的变体,但如果需要,也可以提供一个函数式接口
public static final PropertyDispatch<VariantMutator> ROTATION_HORIZONTAL_FACING = PropertyDispatch.modify(BlockStateProperties.HORIZONTAL_FACING)
    .select(Direction.EAST, BlockModelGenerators.Y_ROT_90)
    .select(Direction.SOUTH, BlockModelGenerators.Y_ROT_180)
    .select(Direction.WEST, BlockModelGenerators.Y_ROT_270)
    .select(Direction.NORTH, BlockModelGenerators.NOP);

// 然后,在可以访问 `Consumer<BlockModelDefinitionGenerator>` blockStateOutput 的地方
this.blockStateOutput.accept(
    MultiVariantGenerator.dispatch(EXAMPLE_BLOCK).with(ROTATION_HORIZONTAL_FACING)
);
  • net.minecraft.client.data.models
    • BlockModelGenerators
      • nonOrientableTrapdoor -> NON_ORIENTABLE_TRAPDOOR,现在是静态的
      • 常量现在可用于常见的 VariantMutator,例如将方块模型旋转一定角度
      • texturedModels -> TEXTURED_MODELS,现在是静态的
      • MULTIFACE_GENERATOR 现在是私有的
      • plainModel - 从模型位置创建一个变体。
      • variantvariants - 从一些 Variant 创建一个常规的 MultiVariant
      • plainVariant - 从其位置创建一个只有一个模型的 MultiVariant
      • condition - 为多部分模型创建一个新的条件构建器
      • or - 对多个条件进行 OR 操作。
      • 大多数生成器方法现在返回 BlockModelDefinitionGeneratorVariantMultiVariant,并接受一个 VariantMultiVariant 而不是指向所需模型的 ResourceLocation
        • VariantProperties 已被 VariantMutator 取代
        • Condition$TerminalConditionCondition 取代
      • createHorizontalFacingDispatchcreateHorizontalFacingDispatchAltcreateTorchHorizontalDispatch 已移除
      • createFacingDispatch 已移除
      • createRotatedVariant(Block, ResourceLocation) 已移除
      • selectMultifaceProperties - 基于提供的 BlockState 和方向到属性函数,创建一个属性到 VariantMutator 的映射。
      • applyRotation 不再接受 Variant,并返回一个 VariantMutator
    • ItemModelGenerators#generateSpawnEgg 已移除
    • ModelProvider#saveAll 已移除
  • net.minecraft.client.data.models.blockstates
    • BlockStateGenerator -> BlockModelDefinitionGenerator,不是一对一
    • Condition -> net.minecraft.client.renderer.block.model.multipart.Condition,不是一对一
      • validate -> instantiate,不是一对一
    • ConditionBuilder - 使用属性值构建一个条件
    • MultiPartGenerator 现在实现 BlockModelDefinitionGenerator
      • with(List<Variant>) -> with(MultiVariant)
      • with(Variant) 已移除
      • with(Condition, ...) -> with(Condition, MultiVariant)
        • 接受 ConditionBuilder 的重载
      • $ConditionalEntry$Entry 已移除
    • MultiVariantGenerator 现在实现 BlockModelDefinitionGenerator
      • multiVariant -> dispatch
      • multiVariant(Block, ...) -> dispatch(Block, MultiVariant)
      • $Empty - 一个匹配每个方块状态的多变体条目。
    • PropertyDispatch 有一个包含分派值的泛型
      • 泛型 V 替换了所有 List<Variant> 的值
      • propertyproperties -> initialmodify
      • $C*#generateList 方法已移除
      • $*Function 已移除
    • Selector -> PropertyValueList,不是一对一
    • Variant -> net.minecraft.client.renderer.block.model.Variant,不是一对一
    • VariantProperties -> net.minecraft.client.renderer.block.model.VariantMutator,不是一对一
    • VariantProperty -> net.minecraft.client.renderer.block.model.VariantMutator$VariantProperty,不是一对一
  • net.minecraft.client.renderer.ItemInHandRenderer#renderItem 不再接受表示物品是否在左手中的布尔值
  • net.minecraft.client.renderer.block
    • BlockModelShaper#stateToModelLocationstatePropertiesToString 已移除
    • BlockRenderDispatcher#renderBatched 现在接受一个 BlockModelPart 列表而不是 RandomSource
    • ModelBlockRenderer
      • tesselateBlocktesselateWithAOtesselateWithoutAO 不再接受 RandomSource,并将 BlockStateModel 替换为 BlockModelPart 列表
      • renderModel 现在是静态的,不再接受 BlockState
      • $AmbientOcclusionFace -> $AmbientOcclusionRenderStorage
      • $CommonRenderStorage - 一个类,保存用于在其给定位置渲染方块的一些元数据。
      • $SizeInfo 现在接受直接索引,而不是从其方向和翻转布尔值计算信息
  • net.minecraft.client.renderer.block.model
    • BakedQuad 现在是一个记录
    • BlockElement 现在是一个记录
      • fromto 现在是 Vector3fc
    • BlockElementFace 现在接受一个 Quadrant 作为面旋转
      • getUgetV - 返回旋转后的纹理坐标。
      • $Deserializer#getTintIndex 现在是私有的和静态的
    • BlockFaceUV -> BlockElementFace$UVs,不是一对一
    • BlockModel 现在是一个记录,接受一个 UnbakedGeometry 而不是直接的 BlockElement 列表
      • $Deserializer#getElements 现在返回一个 UnbakedGeometry
    • BlockModelDefinition 现在是一个记录,接受 $SimpleModelSelectors$MultiPartDefinition
      • GSONfromStreamfromJsonElement -> CODEC,不是一对一
      • instantiate 现在接受一个提供的字符串而不是直接的字符串
      • $Deserializer 已移除
      • $MultiPartDefinition - 一个记录,保存用于获取多部分模型的选择器列表。
      • $SimpleModelSelectors - 一个记录,保存变体到其未烘焙模型实例的映射。
    • BlockModelPart - 方块的烘焙模型表示。
    • BlockStateModel - 方块状态的烘焙表示。
      • collectParts - 获取用于渲染此状态的烘焙模型列表。
      • $SimpleCachedUnbakedRoot - 一个类,表示某个 $Unbaked 模型的委托。
      • $Unbaked - 一个可以创建 $SimpleCachedUnbakedRoot$UnbakedRoot 的扩展
    • FaceBakery
      • bakeQuad 现在接受 Vector3fc 而不是 Vector3f
      • recomputeUVs 已移除
      • extractPositions - 提取面的位置并将它们传递给一个消费者以供使用。
    • ItemTransform 现在是一个记录,向量是 Vector3fc
    • MultiVariant -> net.minecraft.client.data.models.MultiVariant
      • CODEC
      • with - 创建一个带有指定修改器的 MultiVariant
      • $Deserializer 类已移除
    • SimpleModelWrapper 现在实现 BlockModelPart
    • SimpleUnbakedGeometry - 一个保存要烘焙的 BlockElement 列表的未烘焙几何体。
    • SingleVariant - 一个 BlockStateModel 实现,其状态只有一个模型。
    • UnbakedBlockStateModel -> BlockStateModel$UnbakedRoot
    • Variant 不再实现 ModelState,现在接受 $SimpleModelState 而不是直接的旋转和 uv 锁定
      • 构造函数现在有一个只提供 ResourceLocation 的重载,不再接受权重,将其留给 MultiVariant
      • CODEC
      • withXRotwithYRotwithUvLockwithModelwithStatewith - 将变体变异为一个应用了给定设置的新对象。
      • $Deserializer 类已移除
      • $SimpleModelState - 一个记录,保存 x/y 旋转和 uv 锁定。
    • VariantMutator - 一个变体上的一元运算符,将指定设置应用于变体。在状态生成期间使用。
  • net.minecraft.client.renderer.block.model.multipart
    • AndConditionOrCondition -> CombinedCondition,不是一对一
    • KeyValueCondition 现在是一个记录,接受一个要测试的键到术语的映射
    • MultiPart -> MultiPartModel$Unbaked
      • $Definition
        • CODEC
        • getMultiVariants 已移除
      • $Deserializer 类已移除
    • Selector 现在是一个记录,接受一个 BlockStateModel$Unbaked 而不是 MultiVariant
      • $Deserializer 类已移除
  • net.minecraft.client.renderer.entity.ItemRenderer
    • renderItem 现在接受一个 List<BakedQuad> 而不是 BakedModel
    • renderStatic 不再接受一个表示物品握在哪只手中的布尔值
  • net.minecraft.client.renderer.item
    • BlockModelWrapper 现在有一个公共构造函数,接受染色源列表、四边形列表和 ModelRenderProperties
      • 四边形列表和 ModelRenderProperties 取代了直接的 BakedModel,或者现在的 BlockStateModel
      • computeExtents - 将烘焙四边形的顶点提取到一个数组中。
    • ItemModel$BakingContext#bake 已移除
    • ItemModelResolver#updateForLivingupdateForTopItem 不再接受表示物品是否在左手中的布尔值
    • ItemStackReenderState
      • isGui3d 已移除
      • transform 已移除
      • visitExtents - 访问模型要渲染的所有顶点,并将它们传递给提供的消费者。
      • $LayerRenderState
        • NO_EXTENTS_SUPPLIER - 一个空的顶点列表。
        • setupBlockModel 已被拆分为 prepareQuadListsetRenderTypesetUsesBlockLightsetExtentssetParticleIconsetTransform
        • setupSpecialModel 不再接受基础 BakedModel
    • MissingItemModel 现在接受一个 BakedQuad 列表和 ModelRenderProperties,而不是直接的 BakedModel
    • ModelRenderProperties - 用于渲染模型的属性,通常从 ResolvedModel 检索。
    • SpecialModelRenderer 现在接受 ModelRenderProperties 而不是基础 BakedModel
  • net.minecraft.client.resources.model
    • BakedModel -> net.minecraft.client.resources.model.QuadCollection,不是一对一
    • BlockModelRotation
      • by 现在接受 Quadrant 而不是整数
      • withUvLock - 返回带有旋转和声明锁定 UV 用于旋转的模型状态。
    • BlockStateDefinitions - 一个用于创建方块名称到其状态定义映射的管理器。
    • BlockStateModelLoader
      • ModelResourceLocation 字段已移除
      • loadBlockState 不再接受缺失模型
      • $LoadedModel 类已移除
      • $LoadedModels 现在接受一个 BlockStateModel$UnbakedRoot 而不是 $Unbaked
        • forResolvingplainModels 已移除
    • DelegateBakedModel -> net.minecraft.client.renderer.block.model.SimpleModelWrapper,不是一对一
    • MissingBlockModel#VARIANT 已移除
    • ModelBaker
      • bake -> getModel,不是一对一
        • 烘焙器只是检索 ResolvedModel
      • rootName 已移除
      • compute - 计算包含 ModelBaker 的提供的键。通常用于烘焙 BlockStateModel
      • $SharedOperationKey - 一个接口,通常计算未烘焙模型的某个烘焙过程。
    • ModelBakery 现在接受一个 Map<BlockState, BlockStateModel$UnbakedRoot> 用于未烘焙的方块状态模型,一个 Map<ResourceLocation, ResolvedModel> 用于加载的模型,以及一个 ResolvedModel 用于缺失模型
      • bakeModels 现在接受一个 SpriteGetter 和一个 Executor,同时返回一个 CompletableFuture 用于并行加载和烘焙
      • $BakingResult 现在接受一个 $MissingModels 用于缺失的方块状态和物品模型,以及一个 Map<BlockState, BlockStateModel> 用于烘焙的方块状态模型;缺失的物品模型存储在 $MissingModels
      • $MissingModels - 保存方块状态和物品的缺失模型。
      • $TextureGetter 接口已移除
    • ModelDebugName 不再继承 Supplier<String>,而是使用 debugName
    • ModelDiscovery
      • registerSpecialModels 已移除
      • discoverDependencies 现在是私有的
      • getReferencedModelsgetUnreferencedModels 已移除
      • addSpecialModel - 将一个根模型添加到任意加载的模型列表中。
      • missingModel - 返回缺失模型
      • resolve - 解析所有模型依赖关系,返回模型名称到其模型的映射。
    • ModelGroupCollector$GroupKey#create 现在接受一个 BlockStateModel$UnbakedRoot 而不是 $Unbaked
    • ModelManager
      • getModel 已移除
      • getMissingModel -> getMissingBlockStateModel
      • $ResolvedModels - 一个包含已解析依赖关系的模型的映射。
    • ModelResourceLocation 记录已移除
    • ModelState
      • getRotation -> transformation
      • isUvLocked 已移除
      • faceTransfomrationinverseFaceTransformation - 处理返回用于烘焙面顶点的变换后的 Matrix4fc
    • MultiPartBakedModel -> net.minecraft.client.renderer.block.model.multipart.MultiPartModel
      • 现在实现 BlockStateModel 而不是继承 DelegateBakedModel
      • $SharedBlockState - 一个持有者,包含映射到其 $SelectorBlockStateModel
    • QuadCollection - 一个包含要基于关联方向和剔除渲染的四边形列表的数据对象。
    • ResolvableModel$Resolver#resolve -> markDependency,不是一对一
      • 不再直接解析,而是标记依赖关系以供后续后处理步骤使用
    • ResolvedModel - 一个 UnbakedModel,其模型和纹理依赖关系已被完全解析。
    • SimpleBakedModel -> net.minecraft.client.renderer.block.model.SimpleModelWrappernet.minecraft.client.renderer.block.model.SimpleUnbakedGeometry,不是一对一
    • SpriteGetter
      • getreportMissingReference 现在接受 ModelDebugName
      • resolveSlot - 将 TextureSlot 中的键解析为其 TextureAtlasSprite
    • UnbakedGeometry - 一个接口,构造在烘焙时要渲染的四边形集合。
    • UnbakedModel 不再实现 ResolvableModel
      • DEFAULT_AMBIENT_OCCLUSIONDEFAULT_GUI_LIGHT 已移除
      • PARTICLE_TEXTURE_REFERENCE - 保存表示粒子纹理的键。
      • bake 已移除
      • getAmbientOcclusion -> ambientOcclusion
      • getGuiLight -> guiLight
      • getTransforms - transforms
      • getTextureSlots - textureSlots
      • geometry - 保存表示模型元素的未烘焙几何体。
      • getParent -> parent,不是一对一
      • bakeWithTopModelValues 已移除
      • getTopTextureSlotsgetTopAmbientOcclusiongetTopGuiLightgetTopTransformgetTopTransforms 已移除
    • WeightedBakedModel -> WeightedVariants
      • 现在实现 BlockStateModel 而不是继承 DelegateBakedModel
  • net.minecraft.world.item.ItemDisplayContext#leftHand - 返回显示上下文是否正在使用实体的左手渲染。

小幅迁移

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

实体引用

通常,存储另一个实体的 UUID 是为了稍后获取该实体以执行某些逻辑。然而,如果实体在某个时间点被移除,存储原始实体可能会导致问题。因此,添加了 EntityReference 来处理从 UUID 解析实体,同时确保在查询时它仍然存在。

EntityReference 只是一个包装的 Either,要么持有实体实例,要么持有 UUID。当通过 getEntity 解析时,它将尝试验证存储的实体(如果存在)是否未被移除。如果被移除,它将获取 UUID 以再次查找实体本身。如果该实体确实存在,则返回它,否则返回 null。

实体中对 UUID 的大多数引用已被替换为 EntityReference 以促进此更改。

  • net.minecraft.network.syncher.EntityDataSerializers#OPTIONAL_UUID -> OPTIONAL_LIVING_ENTITY_REFERENCE,不是一对一,因为它可以持有实体引用
  • net.minecraft.server.level.ServerLevel#getEntity(UUID) -> Level#getEntity(UUID)
  • net.minecraft.world.entity
    • EntityReference - 一个对实体的引用,要么通过其在世界中的实体实例,要么通过 UUID。
    • LivingEntity#lastHurtByPlayerlastHurtByMob 现在是 EntityReference
    • OwnableEntity
      • getOwnerUUID -> getOwnerReference,不是一对一
      • level 现在返回一个 Level 而不是 EntityGetter
    • TamableAnimal#setOwnerUUID -> setOwnersetOwnerReference;不是一对一
  • net.minecraft.world.entity.animal.horse.AbstractHorse#setOwnerUUID -> setOwner,不是一对一
  • net.minecraft.world.level.Level 现在实现 UUIDLookup<Entity>
  • net.minecraft.world.level.entity
    • EntityAccess 现在实现 UniquelyIdentifyable
    • UniquelyIdentifyable - 一个声称对象具有 UUID 并跟踪对象是否被移除的接口。
    • UUIDLookup - 一个通过 UUID 查找类型的接口。

解作用域玩家参数

许多接受 Player 的方法已被解作用域,根据用例接受 LivingEntityEntity。以下方法是此情况的非详尽列表。

  • net.minecraft.world.entity.EntityType
    • spawn
    • createDefaultStackConfigappendDefaultStackConfig
    • appendCustomEntityStackConfigupdateCustomEntityTag
  • net.minecraft.world.item
    • BucketItem#playEmptySound
    • DispensibleContainerItem#checkExtraContentemptyContents
  • net.minecraft.world.level
    • Level
      • playSeededSound
      • mayInteract
    • LevelAccessor
      • playSound
      • levelEvent
  • net.minecraft.world.level.block
    • BucketPickup#pickupBlock
    • LiquidBlockContainer#canPlaceLiquid
  • net.minecraft.world.level.block.entity.BrushableBlockEntity#brush

组件交互事件

MutableComponent 上的点击和悬停事件已被重做为类似 MapCodec 注册表的系统。它们现在都是接口,将其编解码器注册到一个 $Action 枚举。然后,该实现创建一个引用 $Action 类型的编解码器,并存储逻辑应用所需的任何必要信息。然而,没有与组件交互关联的直接“动作”逻辑。相反,它们被硬编码到它们的使用位置。对于点击事件,是在 Screen#handleComponentClicked 中。对于悬停事件,是在 GuiGraphics#renderComponentHoverEffect 中。因此,任何添加的额外事件都需要注入到枚举以及这两个位置之一或两者中。

  • net.minecraft.network.chat
    • ClickEvent 现在是一个接口
      • getAction -> action
      • getValue 现在根据需要在其子类上,用于其各自的类型
    • HoverEvent 现在是一个接口
      • getAction -> action
      • $EntityTooltipInfo
        • CODEC 现在是一个 MapCodec
        • legacyCreate 已移除
      • $ItemStackInfo 已移除,被 $ShowItem 取代
      • $LegacyConverter 接口已移除

纹理图集重做

纹理图集逻辑已最终确定为一个注册表编解码器系统;然而,图集数据的查询方式已更改。首先,所有图集标识符存储在 AtlasIds 中,而相应的纹理位置存储在 Sheets 中。要从图集中获取材质,使用 MaterialMapper 作为纹理位置和要附加到材质的关联前缀的包装器。然后可以通过 apply 传入您想要使用的材质的 id 来获得 Material

例如:

// 在 sheets 中找到
public static final MaterialMapper ITEMS_MAPPER = new MaterialMapper(TextureAtlas.LOCATION_BLOCKS, "item");
public static final MaterialMapper BLOCKS_MAPPER = new MaterialMapper(TextureAtlas.LOCATION_BLOCKS, "block");

// 查找位于 `assets/examplemod/textures/item/example_item.png` 的纹理的材质
public static final Material EXAMPLE_ITEM = ITEMS_MAPPER.apply(ResourceLocation.fromNamespaceAndPath("examplemod", "example_item"));

// 查找位于 `assets/examplemod/textures/block/example/block.png` 的纹理的材质
public static final Material EXAMPLE_BLOCK = ITEMS_MAPPER.apply(ResourceLocation.fromNamespaceAndPath("examplemod", "example/block"));
  • net.minecraft.client.data.AtlasProvider - 用于生成纹理图集提供者的数据提供者。
  • net.minecraft.client.data.models.ItemModelGenerators
    • SLOT_* -> TRIM_PREFIX_*,现在是公开的,并且是 ResourceLocation
    • TRIM_MATERIAL_MODELS 现在是公开的
    • generateTrimmableItem 现在接受 ResourceLocation 而不是 String
    • $TrimMaterialData 现在是公开的,接受 MaterialAssetGroup 而不是名称和覆盖材质
  • net.minecraft.client.renderer
    • MaterialMapper - 一个存储图集纹理位置和应用于纹理中 id 的前缀的对象。
    • Sheets
      • *_MAPPER - 每个纹理图集纹理的 MaterialMapper
      • createBedMaterial(ResourceLocation) 已移除
      • createShulkerMaterial(ResourceLocation) 已移除
      • createSignMaterial(ResourceLocation) 已移除
      • chestMaterial(String)chestMaterial(ResourceLocation) 已移除
      • createDecoratedPotMaterial(ResourceLocation) 已移除
  • net.minecraft.client.renderer.blockentity.ConduitRenderer#MAPPER - 一个从方块图集获取潮涌核心纹理的映射器。
  • net.minecraft.client.renderer.texture.atlas
    • SpriteSource#type -> codec,不是一对一
    • SpriteSources 现在包含类似于客户端注册表的逻辑,通过其 id 映射器
    • SpriteSourceType 记录已移除
  • net.minecraft.client.renderer.texture.atlas.sources
    • DirectoryLister 现在是一个记录
    • PalettedPermutations 现在是一个记录
    • SingleFile 现在是一个记录
    • SourceFilter 现在是一个记录
    • Unstitcher 现在是一个记录
      • $Region 现在是公开的
  • net.minecraft.client.resources.model.AtlasIds - 一个保存所有原版纹理图集的 ResourceLocation 的类。

注册表上下文交换器

客户端物品现在存储一个 RegistryContextSwapper,用于正确检查访问注册表对象的客户端物品信息。在等级加载之前,它会获得一个占位符以避免崩溃,并在渲染期间用正确的值填充。

  • net.minecraft.client.multiplayer
    • CacheSlot - 一个包含从某个上下文计算出的值的对象。更新时,先前的值被覆盖,上下文注册该槽位以进行清理。
    • ClientLevel 现在实现 CacheSlot$Cleaner
  • net.minecraft.client.renderer.item
    • ClientItem 现在可以接受一个可为 null 的 RegistryContextSwapper
      • withRegistrySwapper - 在 ClientItem 中设置 RegistryContextSwapper
    • ItemModel$BakingContext 现在接受一个 RegistryContextSwapper
  • net.minecraft.util
    • PlaceholderLookupProvider - 一个包含引用对象的占位符的提供者。在客户端物品中使用,因为它们将在 RegistyAccess 填充之前加载。
    • RegistryContextSwapper - 一个用于将某个对象换成另一个不同对象的接口。由客户端物品用于将占位符换成加载的 RegistryAccess

重载实例创建

重载实例已被稍微重新排列。SimpleReloadInstance 基础现在只接受 List<PreparableReloadListener>,其他字段被传入 of 函数,以便可以立即调用 #startTasks

  • net.minecraft.server.packs.resources
    • ProfiledReloadInstance 构造函数现在是私有的,通过 of 访问
    • SimpleReloadInstance 只接受 List<PreparableReloadListener>
      • of 现在返回一个 ReloadInstance,不是一对一
      • allPreparations 现在是包私有的
      • allDone 现在是私有的
      • startTasks - 开始重载监听器。
      • prepareTasks - 运行执行器并设置读取和加载所有所需数据所需的 future。
      • StateFactory$SIMPLE - 一个调用 PreparableReloadListener#reload 的工厂

方块效果应用器

当实体在方块内部时应用于实体的效果现在通过 InsideBlockEffectApplierInsideBlockEffectType 处理。InsideBlockEffectType 是一个枚举,包含一个消费者,用于在调用时应用到实体上。另一方面,InsideBlockEffectApplier 存储在实体上,作为一种基于枚举序数以有序方式应用效果的方法。

要调用其中一种效果类型,您必须覆盖 BlockBehaviour#entityInsideFluid#entityInside 并调用 InsideBlockEffectApplier#apply。如果某些内容应在效果类型之前应用,例如在细雪中冻结之前灭火,则应在 apply 之前调用 InsideBlockEffectApplier#runBefore。类似地,如果某些内容应在之后运行,例如在被放入熔岩后伤害敌人,则应调用 runAfter

// 在某个方块或流体子类中
@Override
protected void entityInside(Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier applier) {
    applier.runBefore(InsideBlockEffectType.EXTINGUISH, entity -> {
        // 在此处修改实体。
    });

    // 执行存储在类型上的基本应用逻辑
    applier.apply(InsideBlockEffectType.FIRE_IGNITE);

    applier.runAfter(InsideBlockEffectType.FIRE_IGNITE, entity -> {
        // 执行由于效果应用而产生的任何最终检查
        entity.hurt(...);
    });
}
  • net.minecraft.world.entity
    • InsideBlockEffectApplier - 一个接口,定义实体在给定方块内时应如何交互。
    • InsideBlockEffectType - 一个枚举,定义当在引用该类型的特定方块内部时要执行的行为。
  • net.minecraft.world.level.block.state.BlockBehaviour#entityInside$BlockStateBase#entityInside 现在接受一个 InsideBlockEffectApplier
  • net.minecraft.world.level.material.Fluid#entityInsideFluidState#entityInside - 每当实体被认为在流体的边界框内时调用的方法。

定时器回调,加入编解码器俱乐部!

用于在服务器计划中执行事件的 TimerCallback,通常是数据包中的 mcfunctions,现在已被重做为编解码器形式。这意味着可以通过将 MapCodec 传递给 TimerCallbacks#register(通过 TimerCallbacks#SERVER_CALLBACKS)而不是序列化器,将回调注册到可用回调列表中。

  • net.minecraft.world.level.timers
    • FunctionCallback 现在是一个记录
    • FunctionTagCallback 现在是一个记录
    • TimerCallback
      • codec - 返回用于序列化的编解码器。
      • $Serializer 类已移除
    • TimerCallbacks
      • serializedeserialize -> codec,不是一对一

JOML 后端接口

Mojang 选择通过传递其逻辑对象的实现接口(通常附加一个 c)来减少对 JOML 对象的限制。例如,Vector3f 变成 Vector3fcMatrix4f 变成 Matrix4fc。这不会改变任何逻辑本身,因为 c 接口由类组件实现。

标签变更

  • minecraft:worldgen/biome
    • spawns_cold_variant_farm_animals
    • spawns_warm_variant_farm_animals
  • minecraft:block
    • sword_instantly_mines
    • replaceable_by_mushrooms
    • plays_ambient_desert_block_sounds
    • edible_for_sheep
    • dead_bush_may_place_on -> dry_vegetation_may_place_on
    • camels_spawnable_on
  • minecraft:cat_variant 已移除
  • minecraft:entity_type
    • can_equip_saddle
    • can_wear_horse_armor
  • minecraft:item
    • book_cloning_target
    • eggs
    • flowers

状态效果字段重命名

一些状态效果已重命名为其游戏内名称,而不是某些内部描述符。

  • MOVEMENT_SPEED -> SPEED
  • MOVEMENT_SLOWDOWN -> SLOWNESS
  • DIG_SPEED -> HASTE
  • DIG_SLOWDOWN -> MINING_FATIGUE
  • DAMAGE_BOOST -> STRENGTH
  • HEAL -> INSTANT_HEALTH
  • HARM -> INSTANT_DAMAGE
  • JUMP -> JUMP_BOOST
  • CONFUSION -> NAUSEA
  • DAMAGE_RESISTANCE -> RESISTANCE

非常技术性的变更

这是一个技术变更列表,根据您的具体设置可能导致高度特定的错误。

  • minecraft:patch_sugar_cane 功能和 minecraft:patch_pumpkin 功能的顺序已交换(先南瓜,后甘蔗),这意味着生成这两个功能的模组生物群系需要将其 JSON 更新为新顺序。

  • 几个原版橡树和树选择器功能现在末尾附加了 _leaf_litter

    • 例如:trees_birch_and_oak -> trees_birch_and_oak_leaf_litter

新增列表

  • net.minecraft
    • ChatFormatting#COLOR_CODEC
    • CrashReportCategory#populateBlockLocationDetails - 将方块位置详细信息添加到崩溃报告。
  • net.minecraft.advancements.critereon.MinMaxBounds#createStreamCodec - 为 MinMaxBounds 实现构造一个流编解码器。
  • net.minecraft.client.Options#startedCleanly - 设置游戏上次启动时是否干净启动。
  • net.minecraft.client.data.models
    • BlockModelGenerators#createSegmentedBlock - 生成一个具有水平旋转的多部分方块状态定义,根据某个整数属性显示最多四个模型。
    • ItemModelGenerators#prefixForSlotTrim - 为某个槽位中的纹饰生成一个原版 ResourceLocation
  • net.minecraft.client.MouseHandler
    • fillMousePositionDetails - 将有关当前鼠标位置和屏幕大小的详细信息添加到崩溃报告。
    • getScaledXPos - 获取由 GUI 缩放选项缩放的当前 x 位置。
    • getScaledYPos - 获取由 GUI 缩放选项缩放的当前 y 位置。
    • drawDebugMouseInfo - 将有关鼠标缩放位置的信息绘制到屏幕。
  • net.minecraft.client.gui.components.toasts.Toast#getSoundEvent - 返回显示吐司时要播放的声音。
  • net.minecraft.client.gui.screens.options.VideoSettingsScreen#updateFullscreenButton - 将全屏选项设置为指定的布尔值。
  • net.minecraft.client.model.geom.builders
    • MeshDefinition#apply - 在返回新实例之前将给定的变换器应用于网格。
    • MeshTransformer#IDENTITY- 执行恒等变换。
  • net.minecraft.client.multiplayer.ClientPacketListener#decoratedHashOpsGenenerator - 返回用于创建数据组件及其值的哈希值的生成器。
  • net.minecraft.client.particle
    • FallingLeavesParticle$TintedLeavesProvider - 一个 FallingLeavesParticle 的提供者,使用粒子生成位置上方的方块指定的颜色。
    • FireflyParticle - 一个在给定的非空气方块位置周围生成萤火虫的粒子。
  • net.minecraft.client.renderer
    • BiomeColors#getAverageDryFoliageColor - 返回干燥生物群系的平均树叶颜色。
    • LevelRenderer$BrightnessGetter - 一个在给定方块位置获取打包亮度的接口。
    • WorldBorderRenderer#invalidate - 使世界边界的当前渲染无效,以便重新渲染。
  • net.minecraft.client.renderer.entity
    • EntityRenderDispatcher#getRenderer - 从渲染状态上存储的数据中获取要使用的渲染器。
    • EntityRenderer#extractAdditionalHitboxes - 当启用“显示碰撞箱”调试状态时,获取要渲染的任何其他碰撞箱。
  • net.minecraft.client.renderer.entity.state
    • EntityRenderState
      • entityType - 实体的类型。
      • hitboxesRenderState - 相对于实体位置的实体的碰撞箱信息。
      • serverHitboxesRenderState - 从服务器同步的实体的碰撞箱信息。
      • fillCrashReportCategory - 设置与渲染状态相关的任何崩溃的详细信息。
    • HitboxesRenderState - 相对于实体位置的实体碰撞箱的渲染状态。
    • HitboxRenderState - 要渲染的单个碰撞箱的渲染状态及其颜色,例如实体的眼睛高度。
    • ServerHitboxesRenderState - 包含来自相关服务器实体的最后同步信息的渲染状态。
    • PigRenderState#variant - 猪的变体。
  • net.minecraft.client.renderer.item.SelectItemModel$ModelSelector - 一个函数式接口,根据开关情况和级别选择物品模型。
  • net.minecraft.client.renderer.item.properties.conditional.ComponentMatches - 一个条件属性,检查给定的谓词是否匹配组件数据。
  • net.minecraft.client.renderer.item.properties.select
    • ComponentContents - 一个开关情况属性,作用于数据组件内的内容。
    • SelectItemModelProperty#valueCodec - 返回属性类型的 Codec
  • net.minecraft.client.resources.DryFoliageColorReloadListener - 一个加载干燥树叶颜色图的重新加载监听器。
  • net.minecraft.commands.arguments.ComponentArgument#getResolvedComponent - 构造一个包含其内容已解析信息的组件。
  • net.minecraft.core
    • Direction#getUnitVec3f - 返回方向的浮点单位向量。
    • HolderGetter$Provider#getOrThrow - 从资源键获取一个持有者引用。
    • SectionPos#sectionToChunk - 将压缩的部分位置转换为压缩的区块位置。
    • Vec3i#STREAM_CODEC
  • net.minecraft.network
    • HashedPatchMap - 一个记录,包含组件到其哈希类型/值的映射,以及一组已移除的组件。
    • HashedStack - 一个 ItemStack 表示,对存储的组件进行哈希处理。
    • ProtocolInfo$DetailsProvider - 为给定的协议提供详细信息。
    • SkipPacketDecoderException - 当解码期间发生错误时抛出的异常,其数据被忽略。
    • SkipPacketEncoderException - 当编码期间发生错误时抛出的异常,其数据被忽略。
  • net.minecraft.network.chat
    • LastSeenMessages
      • computeChecksum - 计算表示所有消息签名的合并校验和的字节。
      • $Update#verifyChecksum - 验证更新校验和是否与最后看到的消息中的校验和匹配。
    • LastSeenMessagesValidator$ValidationException - 如果无法验证消息则抛出的异常。
    • MessageSignature
      • describe - 返回消息签名的字符串化版本。
      • checksum - 将签名中的字节哈希为单个整数。
    • PlayerChatMessage#describeSigned - 返回聊天消息的字符串化版本。
  • net.minecraft.network.codec
    • ByteBufCodecs
      • LONG_ARRAY
      • lengthPrefixed - 返回一个将缓冲区大小限制为给定大小的操作。
    • IdDispatchCodec$DontDecorateException - 一个接口,告诉异常处理程序重新抛出原始异常,而不是将其包装在 EncoderException 中。
  • net.minecraft.network.protocol
    • CodecModifier - 一个使用给定对象修改某个编解码器的函数。
    • ProtocolInfoBuilder#context*Protocol - 使用给定的上下文构建一个 UnboundProtocol,用于修改要发送的编解码器。
  • net.minecraft.network.protocol.game.GameProtocols
    • HAS_INFINITE_MATERIALS - 一个修饰符,检查 ServerboundSetCreativeModeSlotPacket 中玩家是否具有必要的设置。如果没有,则丢弃数据包。
    • $Context - 返回数据包用于修改传入编解码器的上下文。
  • net.minecraft.resources.DelegatingOps
    • $DelegateListBuilder - 一个列表构建器,如果需要可以被子类化。
    • $DelegateRecordBuilder - 一个记录构建器,如果需要可以被子类化。
  • net.minecraft.server.bossevents.CustomBossEvent$Packed - 一个记录,支持用于序列化的事件信息。
  • net.minecraft.server.commands.InCommandFunction - 一个接受某些输入并返回结果的命令函数。
  • net.minecraft.server.level
    • DistanceManager#forEachBlockTickingChucnks - 为每个启用了方块Tick的区块应用提供的消费者。
    • ServerLevel
      • areEntitiesActuallyLoadedAndTicking - 返回实体管理器是否实际上正在Tick并加载给定区块中的实体。
      • tickThunder - 在给定等级内Tick雷声逻辑。
      • anyPlayerCloseEnoughForSpawning - 如果玩家足够接近以在给定位置生成实体,则返回。
    • ServerPlayer$RespawnConfig - 一个包含玩家重生信息的记录。
  • net.minecraft.util
    • AbstractListBuilder - 一个 ops 列表构建器,将实现简化为三个方法:初始化、追加和构建最终列表。
    • Brightness
      • block - 从打包值中返回块光。
      • sky - 从打包值中返回天空光。
    • HashOps - 一个为数据生成哈希码的动态 ops。
    • ExtraCodecs
      • UNTRUSTED_URI - 一个不受游戏信任的 URI 的编解码器。
      • CHAT_STRING - 聊天消息中字符串的编解码器。
      • legacyEnum - 一个将枚举映射到其在 Enum#toString 中的输出的编解码器。
    • FileSystemUtil - 一个用于与文件系统交互的工具。
    • GsonHelper#encodesLongerThan - 返回提供的元素是否可以用指定数量的字符写入。
    • Unit#STREAM_CODEC - 一个用于单位实例的流编解码器。
    • Util
      • mapValues - 使用给定的函数更新映射的值。
      • mapValuesLazy - 使用给定的函数更新映射的值,但每个值在首次访问时解析。
      • growByHalf - 返回一个整数乘以 1.5,向下取整,将值钳制到某个最小值和最大整数大小。
  • net.minecraft.util.random.Weighted#mapWeightedList#map - 将存储的对象转换为新类型。
  • net.minecraft.util.thread.ParallelMapTransform - 一个辅助工具,用于并行处理和批处理任务。
  • net.minecraft.world.effect.MobEffectInstance#withScaledDuration - 构造一个新的实例,其持续时间按某个浮点值缩放。
  • net.minecraft.world.entity
    • AreaEffectCloud#setPotionDurationScale - 设置药水应应用的持续时间比例。
    • DropChances - 一个槽位到概率的映射,表示实体掉落该装备的可能性。
    • Entity
      • isInterpolating - 返回实体是否在两个步骤之间插值。
      • sendBubbleColumnParticles - 从服务器生成气泡柱粒子。
      • canSimulateMovement - 实体的移动是否可以模拟,通常来自玩家。
      • propagateFallToPassengers - 将载具的坠落伤害传播给其乘客。
      • lavaIgnite - 如果实体不免疫,则点燃实体 15 秒。
      • clearFreeze - 将实体被冻结的刻数设置为 0。
      • removeLatestMovementRecordingBatch - 从本Tick执行的所有移动中删除最后一个元素。
    • InterpolationHandler - 一个旨在根据需要轻松处理给定实体的位置和旋转插值的类。
    • LivingEntity
      • getLuck - 返回实体在随机事件中的运气。
      • getLastHurtByPlayersetLastHurtByPlayer - 处理最后伤害此实体的玩家。
      • getEffectBlendFactor - 获取已应用状态效果的混合因子。
      • applyInput - 应用实体的输入作为其 AI,通常用于本地玩家。
      • INPUT_FRICTION - 应用于实体移动的标量。
  • net.minecraft.world.entity.animal.camel.Camel#checkCamelSpawnRules - 检查骆驼是否可以在特定位置生成。
  • net.minecraft.world.entity.animal.sheep.SheepColorSpawnRules - 一个包含绵羊在给定气候下生成时羊毛的颜色生成配置的类。
  • net.minecraft.world.entity.npc.Villager#createDefaultVillagerData - 返回在未设置数据时要使用的村民的默认类型和职业。
  • net.minecraft.world.entity.player.Player
    • preventsBlockDrops - 玩家是否不能掉落任何被破坏的方块。
    • gameMode - 返回玩家的当前游戏模式。
    • debugInfo - 将关于玩家的常见信息作为单个字符串返回。
  • net.minecraft.world.inventory
    • ContainerSynchronizer#createSlot - 创建一个表示对侧槽位的 RemoteSlot
    • RemoteSlot - 一个表示对侧数据的槽位,当数据不一致时进行同步。
  • net.minecraft.world.item
    • EitherHolder#key - 返回持有的注册表对象的资源键。
    • Item#STREAM_CODEC
    • ItemStack
      • OPTIONAL_UNTRUSTED_STREAM_CODEC
      • MAP_CODEC
      • canDestroyBlock - 返回此物品是否可以破坏提供的方块状态。
  • net.minecraft.world.item.alchemy.PotionContents#getPotionDescription - 返回带有某些放大器的状态效果的描述。
  • net.minecraft.world.item.crafting
    • Recipe#KEY_CODEC
    • TransmuteResult - 一个配方结果对象,表示一个物品、数量和应用到的组件。
  • net.minecraft.world.item.equipment.trim.ArmorTrim#layerAssetId - 返回纹饰资源的位置。
  • net.minecraft.world.level
    • BlockGetter$BlockStepVisitor - 一个消费者,接受当前位置以及期望行进路径内的碰撞次数。
    • ColorMapColorUtil - 一个辅助工具,根据生物群系的温度、降水、颜色映射和默认颜色从地图中获取颜色。
    • DryFoliageColor - 用于具有干燥树叶的生物群系的颜色解析器。
    • GameRules
      • getType - 从其键获取游戏规则类型。
      • keyCodec - 为游戏规则类型的键创建编解码器。
    • Level
      • isMoonVisible - 返回月亮当前是否在天空中可见。
      • getPushableEntities - 获取指定目标之外的在提供的边界框内的所有实体。
      • getClientLeafTintColor - 返回指定位置的树叶染色颜色。
      • playPlayerSound - 在客户端向当前玩家播放声音。
    • LevelReader#getHeight - 返回地图在给定位置的高度。
    • NaturalSpawner#INSCRIBED_SQUARE_SPAWN_DISTANCE_CHUNK - 提供玩家足够接近以进行生成的最小距离。
  • net.minecraft.world.level.biome
    • Biome
      • getDryFoliageColorgetDryFoliageColorFromTexture - 获取生物群系的干燥树叶颜色,要么从效果中获取,要么从气候设置中获取。
    • BiomeSpecialEffects#getDryFoliageColorOverride$Builder#dryFoliageColorOverride - 当不从颜色映射纹理中提取时,返回默认的干燥树叶颜色。
  • net.minecraft.world.level.block
    • BaseFireBlock#fireIgnite - 点燃一个实体。
    • Block
      • UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS - 一个标志,在更新方块实体时跳过所有潜在的副作用。
      • UPDATE_SKIP_ALL_SIDEEFFECTS - 一个标志,通过跳过某些方块实体逻辑、抑制掉落和更新已知形状来跳过所有副作用。
      • UPDATE_SKIP_ON_PLACE - 一个标志,在设置时跳过调用 BlockState#onPlace
    • BonemealableBlock#hasSpreadableNeighbourPosfindSpreadableNeighbourPos - 处理在施骨粉时植被可以传播到的其他位置。
    • CactusFlowerBlock - 生长在仙人掌上的花。
    • FireflyBushBlock - 一个在其周围生成萤火虫粒子的灌木。
    • SandBlock - 一个可以播放环境声音的彩色沙子方块。
    • SegmentableBlock - 一个通常可以分解成具有独特大小和位置的部分的方块。
    • ShortDryGrassBlock - 一个已经干枯的单个草方块。
    • TallDryGrassBlock - 一个已经干枯的双高草方块。
    • TerracottaBlock - 一个可以播放环境声音的陶瓦方块。
    • TintParticleLeavesBlock - 一个其粒子被染色的树叶方块。
    • UntintedParticleLeavesBlock - 一个其粒子未被染色的树叶方块。
    • VegetationBlock - 一个表示某种植被的方块,可以传播光线,并需要某种耕地或泥土才能生存。
  • net.minecraft.world.level.block.entity.StructureBlockEntity#isStrictsetStrict - 在生成结构时设置严格模式。
  • net.minecraft.world.level.block.sounds.AmbientDesertBlockSoundsPlayer - 一个辅助工具,用于为给定的方块播放声音,通常在 animateTick 期间。
  • net.minecraft.world.level.block.state.BlockBehaviour#getEntityInsideCollisionShape - 获取实体在其内部时方块的碰撞形状。
  • net.minecraft.world.level.border.WorldBorder
    • closestBorder - 根据玩家的水平方向返回离玩家最近的边界列表。
    • $DistancePerDirection - 一个记录,包含给定方向上世界边界到实体的距离。
  • net.minecraft.world.level.chunk.status.ChunkStatus#CODEC
  • net.minecraft.world.level.entity.PersistentEntitySectionManager#isTicking - 返回指定的区块当前是否正在Tick。
  • net.minecraft.world.level.levelgen.Heightmap$Types#STREAM_CODEC
  • net.minecraft.world.level.levelgen.feature
    • AbstractHugeMushroomFeature#placeMushroomBlock - 在指定位置放置一个蘑菇方块,如果可以则替换方块。
    • FallenTreeFeature - 一个生成带有给定长度树桩的倒伏树木的功能。
    • TreeFeature#getLowestTrunkOrRootOfTree - 返回树装饰器的最低树干位置。
  • net.minecraft.world.level.levelgen.feature.configurations.FallenTreeConfiguration - 用于带有树桩的倒伏树的配置。
  • net.minecraft.world.level.levelgen.feature.treedecorators
    • AttachedToLogsDecorator - 一个装饰器,以一定的概率将随机方块附加到原木的给定方向。
    • PlaceOnGroundDecorator - 一个装饰器,将树放置在有效的方块位置上。
  • net.minecraft.world.level.levelgen.structure.pools
    • ListPoolElement#getElements - 返回结构池的元素。
    • SinglePoolElement#getTemplateLocation - 返回元素使用的模板的位置。
    • StructureTemplatePool#getTemplates - 返回一个带有权重的元素列表。
  • net.minecraft.world.level.levelgen.structure.structures.JigsawStructure
    • getStartPool - 返回要生成的拼图的起始池。
    • getPoolAliases - 返回拼图使用的所有池。
  • net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate#getDefaultJointType - 如果未指定或加载期间发生错误,返回两个拼图块之间的默认连接类型。
  • net.minecraft.world.level.material.Fluid#getAABBFluidState#getAABB - 返回流体的边界框。
  • net.minecraft.world.scores
    • Objective#pack$Packed - 处理目标数据的可序列化形式。
    • PlayerTeam#pack$Packed - 处理玩家队伍数据的可序列化形式。
    • Scoreboard
      • loadPlayerTeamloadObjective - 从打包对象加载数据。
      • $PackedScore - 处理记分板数据的可序列化形式。
  • net.minecraft.world.level.storage.loot.LootTable#KEY_CODEC
  • net.minecraft.world.phys
    • AABB$Builder - 一个用于通过提供内部向量来构造边界框的构建器。
    • Vec2#CODEC
  • net.minecraft.world.phys.shapes.CollisionContext
    • placementContext - 当从其物品放置方块时构造上下文。
    • isPlacement - 返回上下文是否用于放置方块。
  • net.minecraft.world.ticks.TickPriority#CODEC

变更列表

  • net.minecraft.client.Screenshot 现在是一个实用程序而不是实例类,意味着所有实例方法都已移除
    • takeScreenshot(RenderTarget) -> takeScreenshot(RenderTarget, Consumer<NativeImage>),不返回任何内容
  • net.minecraft.client.multiplayer
    • ClientChunkCache#replaceWithPacketData 现在接受一个 Map<Heightmap$Types, long[]> 而不是 CompoundTag
    • MultiPlayerGameMode#hasInfiniteItems -> net.minecraft.world.entity.LivingEntity#hasInfiniteMaterials
    • ClientPacketListener#markMessageAsProcessed 现在接受一个 MessageSignature 而不是 PlayerChatMessage
  • net.minecraft.client.multiplayer.chat.ChatListener#handleChatMessageError 现在接受一个可为 null 的 MessageSignature
  • net.minecraft.client.player
    • ClientInput#leftImpulseforwardImpulse -> moveVector,现在是 protected
    • LocalPlayer#spinningEffectIntensityoSpinningEffectIntensity -> portalEffectIntensityoPortalEffectIntensity
  • net.minecraft.client.renderer.LevelRenderer#getLightColor(BlockAndTintGetter, BlockState, BlockPos) -> getLightColor(LevelRenderer$BrightnessGetter, BlockAndTintGetter, BlockState, BlockPos)
  • net.minecraft.client.renderer.blockentity.BlockEntityRenderer#render 现在接受一个 Vec3 表示相机的位置
  • net.minecraft.client.renderer.chunk.SectionRenderDispatcher
    • $RenderSection
      • getOrigin -> getRenderOrigin
      • reset 现在是公开的
      • releaseBuffers 已移除
    • $CompileTask#getOrigin -> getRenderOrigin
  • net.minecraft.client.renderer.entity
    • DonkeyRenderer 现在接受一个 DonekyRenderer$Type,包含纹理、模型层和装备信息
    • ItemEntityRenderer#renderMultipleFromCount 现在有一个接受模型边界框的重载
    • UndeadHorseRenderer 现在接受一个 UndeadHorseRenderer$Type,包含纹理、模型层和装备信息
  • net.minecraft.client.renderer.entity.layers
    • EquipmentLayerRenderer$TrimSpriteKey#textureId -> spriteId
    • VillagerProfessionLayer#getHatData 现在接受一个资源键到元数据部分的映射,并将注册表和值交换为一个持有者实例
  • net.minecraft.client.renderer.item
    • ConditionalItemModel 现在接受一个 ItemModelPropertyTest 而不是 ConditionalItemModelProperty
    • SelectItemModel 现在接受一个 $ModelSelector 而不是一个对象映射
  • net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperty 现在实现 ItemModelPropertyTest
    • ItemModelPropertyTest 持有之前在 ConditionalItemModelProperty 中的 get 方法
  • net.minecraft.commands.arguments
    • ComponentArgument
      • ERROR_INVALID_JSON -> ERROR_INVALID_COMPONENT
      • getComponent -> getRawComponent
    • ResourceKeyArgument#getRegistryKey 现在是公开的
    • StyleArgument#ERROR_INVALID_JSON -> ERROR_INVALID_STYLE
  • net.minecraft.commands.arguments.item
    • ComponentPredicateParser$Context#createComponentTestcreatePredicateTest 现在接受一个 Dynamic 而不是 Tag
    • ItemPredicateArgument
      • $ComponentWrapper#decode 现在接受一个 Dynamic 而不是 RegistryOpsTag
      • $PredicateWrapper#decode 现在接受一个 Dynamic 而不是 RegistryOpsTag
  • net.minecraft.core
    • BlockMath
      • VANILLA_UV_TRANSFORM_LOCAL_TO_GLOBALVANILLA_UV_TRANSFORM_GLOBAL_TO_LOCAL 现在是私有的
      • getUVLockTransform -> getFaceTransformation
    • Direction#rotate 现在接受一个 Matrix4fc 而不是 Matrix4f
    • Rotations 现在是一个记录
  • net.minecraft.data.loot.BlockLootSubProvider#createPetalDrops -> createSegmentedBlockDrops
  • net.minecraft.network
    • FriendlyByteBuf
      • writeLongArrayreadLongArray 现在有静态委托,接受 ByteBuf,并且 *Fixed* 版本用于固定大小的数组
    • ProtocolInfo$Unbound -> $Detailsnet.minecraft.network.protocol.SimpleUnboundProtocolnet.minecraft.network.protocol.UnboundProtocol;不是一对一
      • #bind -> net.minecraft.network.protocol.SimpleUnboundProtocol#bindUnboundProtocol#bind;不是一对一
    • SkipPacketException 现在是一个接口,而不是 EncoderException 的子类
  • net.minecraft.network.chat
    • ComponentSerialization#flatCodec -> flatRestrictedCodec
    • LastSeenMessages$Update 现在接受一个表示校验和值的字节
    • LastSeenMessagesValidator
      • applyOffset 现在不返回任何内容,并且可以抛出 $ValidationException
      • applyUpdate 现在返回原始消息,并且可以抛出 $ValidationException
  • net.minecraft.network.codec.StreamCodec#composite 现在有一个九个参数的重载
  • net.minecraft.network.protocol.ProtocolInfoBuilder 现在接受第三个泛型,表示如何修改提供的编解码器。
    • addPacket 现在有一个接受 CodecModifier 的重载
    • build -> buildUnbound,不是一对一
    • protocolserverboundProtocolclientboundProtocol 现在返回一个 SimpleUnboundProtocol
  • net.minecraft.network.protocol.ConfigurationProtocols 现在包含 SimpleUnboundProtocol 常量
  • net.minecraft.network.protocol.game
    • ClientboundContainerSetContentPacket 现在是一个记录
    • ClientboundMoveEntityPacket#getyRotgetxRot -> getYRotgetXRot
    • ClientboundPlayerChatPacket 现在接受一个聊天消息的全局索引
    • ClientboundLevelChunkPacketdata#getHeightmaps 现在返回一个 Map<Heightmap.Types, long[]>
    • ClientboundUpdateAdvancementsPacket 现在接受一个布尔值,表示是否将进度显示为吐司
    • GameProtocols 常量现在是 SimpleUnboundProtocolUnboundProtocol
    • ServerboundContainerClickPacket 现在是一个记录
    • ServerboundMovePlayerPacket$Pos$PosRot 现在有一个接受 Vec3 作为位置的重载
    • ServerboundSetStructureBlockPacket 现在接受一个额外的布尔值,表示是否应在严格模式下生成结构
  • net.minecraft.network.protocol.handshake.HandshakeProtocols#SERVERBOUND_TEMPLATE 现在是一个 SimpleUnboundProtocol
  • net.minecraft.network.protocol.login.LoginProtocols#SERVERBOUND_TEMPLATE 常量现在是 SimpleUnboundProtocol
  • net.minecraft.network.protocol.status.StatusProtocols#SERVERBOUND_TEMPLATE 常量现在是 SimpleUnboundProtocol
  • net.minecraft.server.PlayerAdvancements#flushDirty 现在接受一个布尔值,表示进度是否显示为吐司
  • net.minecraft.server.bossevents.CustomBossEvent
    • save -> pack,不是一对一
    • load 现在接受 id 和打包变体以解包
  • net.minecraft.server.level
    • DistanceManager
      • hasPlayersNearby 现在返回一个 TriState
      • forEachBlockTickingChunks -> forEachEntityTickingChunk,不是一对一
    • ServerEntity 现在接受一个消费者,用于向所有玩家广播数据包,但忽略列表中的玩家除外
    • ServerLevel
      • getForcedChunks -> getForceLoadedChunks
      • isPositionTickingWithEntitiesLoaded 现在是公开的
      • isNaturalSpawningAllowed -> canSpawnEntitiesInChunkBlockPos 变体已移除
    • ServerPlayer
      • getRespawnPositiongetRespawnAnglegetRespawnDimensionisRespawnForced -> getRespawnConfig,不是一对一
      • setRespawnPosition 现在接受一个 $RespawnConfig 而不是单独的重生信息
      • loadAndSpawnParentVehicleloadAndSpawnEnderpearls 现在接受一个 CompoundTag,没有可选的包装
  • net.minecraft.server.network.ServerGamePacketListenerImpl 现在实现 GameProtocols$Context
  • net.minecraft.sounds.SoundEvents 有以下声音现在是 Holder 包装的:
    • ITEM_BREAK
    • SHIELD_BLOCKSHIELD_BREAK
    • WOLF_ARMOR_BREAK
  • net.minecraft.util
    • Brightness
      • FULL_BRIGHT 现在是 final
      • pack 现在有一个静态重载,接受块光和天空光。
    • ExtraCodecs#MATRIX4f 现在是一个 Codec<Matrix4fc>
    • Util#makeEnumMap 返回 Map 超实例而不是具体的 EnumMap
  • net.minecraft.util.parsing.packrat.commands.TagParseRule 现在接受一个标签类型的泛型
    • 构造函数现在是公开的,接受一个 DynamicOps
  • net.minecraft.util.profiling
    • ActiveProfiler 现在接受一个 BooleanSupplier 而不是一个布尔值
    • ContinuousProfiler 现在接受一个 BooleanSupplier 而不是一个布尔值
  • net.minecraft.util.worldupdate.WorldUpgrader 现在接受当前的 WorldData
  • net.minecraft.world
    • BossEvent$BossBarColor$BossBarOverlay 现在实现 StringRepresentable
    • Container 现在实现 Iterable<ItemStack>
  • net.minecraft.world.effect
    • MobEffect
      • getBlendDurationTicks -> getBlendInDurationTicksgetBlendOutDurationTicksgetBlendOutAdvanceTicks;不是一对一
      • setBlendDuration 现在有一个接受三个整数来设置淡入、淡出和淡出提前刻的重载
    • MobEffectInstance#tick -> tickServertickClient;不是一对一
  • net.minecraft.world.entity
    • Entity
      • cancelLerp -> InterpolationHandler#cancel
      • lerpTo -> moveOrInterpolateTo
      • lerpTargetXlerpTargetYlerpTargetZlerpTargetXRotlerpTargetYRot -> getInterpolation
      • onAboveBubbleCol -> onAboveBubbleColumn 现在接受一个 BlockPos 作为气泡柱粒子的生成位置
        • 逻辑委托给受保护的静态 handleOnAboveBubbleColumn
      • isControlledByOrIsLocalPlayer -> isLocalInstanceAuthoritative,现在是 final
      • isControlledByLocalInstance -> isLocalClientAuthoritative,现在是 protected
      • isControlledByClient -> isClientAuthoritative
      • fallDistancecauseFallDamage 现在是 double
      • absMoveto -> absSnapTo
      • absRotateTo -> asbSnapRotationTo
      • moveTo -> snapTo
      • sendBubbleColumnParticles 现在是静态的,接受 Level
      • onInsideBubbleColumn 逻辑委托给受保护的静态 handleOnInsideBubbleColumn
    • EntityType
      • POTION -> SPLASH_POTIONLINGERING_POTION,不是一对一
      • $EntityFactory#create 现在可以返回一个 null 实例
    • ExperienceOrb#value -> DATA_VALUE
    • ItemBasedSteering 不再接受用于判断是否有马鞍的访问器
    • LivingEntity
      • lastHurtByPlayerTime -> lastHurtByPlayerMemoryTime
      • lerpStepslerpXlerpYlerpZlerpYRotlerpXRot -> interpolation,不是一对一
      • isAffectedByFluids 现在是公开的
      • removeEffectNoUpdate 现在是 final
      • tickHeadTurn 现在不返回任何内容
      • canDisableShield -> canDisableBlocking,现在通过 WEAPON 数据组件设置
      • calculateFallDamage 现在接受 double 而不是 float
    • Mob
      • handDropChancesarmorDropChancesbodyArmorDropChance -> dropChances,不是一对一
      • getEquipmentDropChance -> getDropChances,不是一对一
  • net.minecraft.world.entity.ai.Brain#addActivityWithConditions 现在有一个接受整数表示起始优先级的重载
  • net.minecraft.world.entity.ai.behavior
    • LongJumpToRandomPos$PossibleJump 现在是一个记录
    • VillagerGoalPackages#get*Package 现在接受一个持有者包装的职业
  • net.minecraft.world.entity.ai.gossip.GossipContainer#storeupdate -> clearputAllcopy;不是一对一
  • net.minecraft.world.entity.animal
    • Pig 现在是一个 VariantHolder
    • Sheep -> .sheep.Sheep
    • WaterAnimal#handleAirSupply 现在接受一个 ServerLevel
  • net.minecraft.world.entity.animal.axolotl.Axolotl#handleAirSupply 现在接受一个 ServerLevel
  • net.minecraft.world.entity.monster.ZombieVillager#setGossips 现在接受一个 GossipContainer
  • net.minecraft.world.entity.monster.warden.WardenSpawnTracker 现在有一个重载,将初始参数设置为零
  • net.minecraft.world.entity.npc
    • Villager 现在接受一个键或一个 VillagerType 的持有者
      • setGossips 现在接受一个 GossipContainer
    • VillagerData 现在是一个记录
      • set* -> with*
    • VillagerProfession 现在接受一个 Component 作为名称
    • VillagerTrades
      • TRADES 现在接受一个资源键作为映射的键
        • 这对于所有其他特定类型的交易类似
      • $FailureItemListing 现在是私有的
  • net.minecraft.world.entity.player.Player
    • stopFallFlying -> LivingEntity#stopFallFlying
    • isSpectatorisCreativePlayer 类中不再是抽象的
  • net.minecraft.world.entity.projectile.ThrownPotion -> AbstractThrownPotion,在 ThrownLingeringPotionThrownSplashPotion 中实现
  • net.minecraft.world.entity.raid.Raid(int, ServerLevel, BlockPos) -> Raid(BlockPos, Difficulty)
    • tickaddWaveMob 现在接受 ServerLevel
  • net.minecraft.world.entity.vehicle
    • AbstractMinecart#setDisplayBlockState -> setCustomDisplayBlockState
    • MinecartBehavior
      • cancelLerp -> InterpolationHandler#cancel
      • lerpTargetXlerpTargetYlerpTargetZlerpTargetXRotlerpTargetYRot -> getInterpolation
    • MinecartTNT#primeFuse 现在接受 DamageSource 原因
  • net.minecraft.world.inventory
    • AbstractContainerMenu
      • setRemoteSlotNoCopy -> setRemoteSlotUnsafe,不是一对一
      • setRemoteCarried 现在接受一个 HashedStack
    • ClickType 现在接受一个表示其表示的 id
    • ContainerSynchronizer#sendInitialData 现在接受一个堆栈列表而不是 NonNullList
  • net.minecraft.world.item
    • EitherHolder 现在接受一个 Either 实例而不是仅仅一个可选的持有者和 ResourceKey
    • Item
      • canAttackBlock -> canDestroyBlock
      • hurtEnemy 不再返回任何内容
      • onCraftedBy 不再接受一个单独的 Level 实例,现在依赖于 Player 提供的实例
    • ItemStack
      • validateStrict 现在是公开的
      • onCraftedBy 不再接受一个单独的 Level 实例,现在依赖于 Player 提供的实例
    • MapItem
      • create 现在接受一个 ServerLevel 而不是 Level
      • lockMap 现在是私有的
    • ThrowablePotionItem 现在是抽象的,包含两个创建 AbstractThrownPotion 实体的方法
    • WrittenBookItem#resolveBookComponents -> WrittenBookContent#resolveForItem
  • net.minecraft.world.item.alchemy.PotionContents 现在实现 TooltipProvider
    • forEachEffectapplyToLivingEntity 现在接受一个 float 表示持续时间的标量
  • net.minecraft.world.item.component.WrittenBookContent 现在实现 TooltipProvider
  • net.minecraft.world.item.crafting
    • SmithingRecipe#baseIngredient 现在返回一个 Ingredient
    • SmithingTransformRecipe 现在接受一个 TransmuteResult 而不是一个 ItemStack 和一个 Ingredient 作为基础
    • SmithingTrimRecipe 现在接受 Ingredient 而不是 Optional 包装的条目,以及一个 TrimPattern 持有者
    • TransmuteRecipe 现在接受一个 TransmuteResult 而不是一个 Item 持有者
  • net.minecraft.world.item.crafting.display.SlotDisplay$SmithingTrimDemoSlotDisplay 现在接受一个 TrimPattern 持有者
  • net.minecraft.world.item.enchantment.EnchantmentInstance 现在是一个记录
  • net.minecraft.world.level
    • BlockGetter#boxTraverseBlocks -> forEachBlockIntersectedBetween,不是一对一
    • CustomSpawner#tick 不再返回任何内容
    • GameRules$Type 现在接受一个值类
    • Level
      • onBlockStateChange -> updatePOIOnBlockStateChange
      • isDay -> isBrightOutside
      • isNight -> isDarkOutside
      • setMapData -> net.minecraft.server.level.ServerLevel#setMapData
      • getFreeMapId -> net.minecraft.server.level.ServerLevel#getFreeMapId
    • LevelAccessor#blockUpdated -> updateNeighborsAt
  • net.minecraft.world.level.biome.MobSpawnSettings$SpawnerData 现在是一个记录
  • net.minecraft.world.level.block
    • AttachedStemBlock 现在继承 VegetationBlock
    • AzaleaBlock 现在继承 VegetationBlock
    • Block#fallOn 现在接受一个 double 作为坠落伤害,而不是 float
    • BushBlock 现在继承 VegetationBlock 并实现 BonemealableBlock
    • ColoredFallingBlock#dustColor 现在是 protected
    • CropBlock 现在继承 VegetationBlock
    • DeadBushBlock -> DryVegetationBlock
    • DoublePlantBlock 现在继承 VegetationBlock
    • FallingBlock#getDustColor 现在是抽象的
    • FlowerBedBlock 现在继承 VegetationBlock
    • FlowerBlock 现在继承 VegetationBlock
    • FungusBlock 现在继承 VegetationBlock
    • LeafLitterBlock 现在继承 VegetationBlock
    • LeavesBlock 现在是抽象的,接受粒子生成的概率
      • 粒子通过 spawnFallingLeavesParticle 生成
    • MangroveLeavesBlock 现在继承 TintedParticleLeavesBlock
    • MushroomBlock 现在继承 VegetationBlock
    • NetherSproutsBlock 现在继承 VegetationBlock
    • NetherWartBlock 现在继承 VegetationBlock
    • ParticleLeavesBlock -> LeafLitterBlock
    • PinkPetalsBlock -> FlowerBedBlock
    • RootsBlock 现在继承 VegetationBlock
    • Rotation 现在有一个用于网络同步的索引
    • SaplingBlock 现在继承 VegetationBlock
    • SeagrassBlock 现在继承 VegetationBlock
    • SeaPickleBlock 现在继承 VegetationBlock
    • StemBlock 现在继承 VegetationBlock
    • SweetBerryBushBlock 现在继承 VegetationBlock
    • TallGrassBlock 现在继承 VegetationBlock
    • TntBlock#prime 现在返回是否生成了点燃的 TNT。
    • WaterlilyBlock 现在继承 VegetationBlock
  • net.minecraft.world.level.block.entity
    • BlockEntity
      • parseCustomNameSafe 现在接受一个可为 null 的 Tag 而不是字符串
      • getPosFromTag 现在接受 ChunkPos
      • $ComponentHolder#COMPONENTS_CODEC 现在是一个 MapCodec
    • BLockEntityType#create 不再是可为 null 的
  • net.minecraft.world.level.block.entity.trialspawner.TrialSpawner#codec 现在返回一个 MapCodec
  • net.minecraft.world.level.block.state.StateHolder
    • getNullableValue 现在是私有的
    • hasProperty 不再包含泛型
  • net.minecraft.world.level.chunk
    • ChunkAccess#setBlockState 现在接受块标志而不是布尔值,并有一个重载来更新所有设置
    • LevelChunk#replaceWithPacketData 现在接受一个 Map<Heightmap$Types, long[]> 而不是 CompoundTag
  • net.minecraft.world.level.chunk.storage.SerializableChunkData#getChunkTypeFromTag -> getChunkStatusFromTag,不是一对一
  • net.minecraft.world.level.gameevent.vibrations.VibrationSystem#DEFAULT_VIBRATION_FREQUENCY -> NO_VIBRATION_FREQUENCY
  • net.minecraft.world.level.levelgen.feature.TreeFeature#isVine 现在是公开的
  • net.minecraft.world.level.levelgen.structure.pools.alias
    • Direct -> DirectPoolAlias
    • Random -> RandomPoolAlias
    • RandomGroup -> RandomGroupPoolAlias
  • net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate$JigsawBlockInfo 现在接受 StructureTemplatePoolResourceKey 而不是原始 ResourceLocation
  • net.minecraft.world.level.saveddata.maps.MapFrame 现在是一个记录
    • saveload -> CODEC,不是一对一
  • net.minecraft.world.level.storage.loot.functions.SetWrittenBookPagesFunction#PAGE_CODEC -> WrittenBookContent#PAGES_CODEC
  • net.minecraft.world.scores
    • Score#write -> CODEC,不是一对一
    • Scoreboard
      • savePlayerScores -> packPlayerScores,不是一对一
      • loadPlayerScores -> loadPlayerScore,不是一对一
    • Team$CollisionRule$Visibility 现在是 StringRepresentable
  • net.minecraft.world.phys.shapes.EntityCollisionContext 现在接受一个布尔值,表示是否用于放置方块
  • net.minecraft.world.ticks.SavedTick
    • loadTicksaveTicksave -> codec,不是一对一
    • loadTickList -> filterTickListForChunk,不是一对一

移除列表

  • com.mojang.blaze3d.vertex.BufferUploader
  • net.minecraft.core.Rotations#getWrapped*
  • net.minecraft.network.chat.ComponentSerialization#FLAT_CODEC
  • net.minecraft.network.protocol.game
    • ClientboundAddExperimentOrbPacket
    • ClientGamePacketListener#handleAddExperienceOrb
  • net.minecraft.resources.ResourceLocation$Serializer
  • net.minecraft.server.network.ServerGamePacketListenerImpl#addPendingMessage
  • net.minecraft.world
    • BossEvent$BossBarColor#byName$BossBarOverlay#byName
    • Clearable#tryClear
  • net.minecraft.world.effect.MobEffectInstance#saveload
  • net.minecraft.world.entity
    • Entity
      • isInBubbleColumn
      • isInWaterRainOrBubbleisInWaterOrBubble
      • newDoubleListnewFloatList
      • recordMovementThroughBlocks
    • EntityEvent#ATTACK_BLOCKEDSHIELD_DISABLED
    • ItemBasedSteering
      • addAdditionalSaveDatareadAdditionalSaveData
      • setSaddlehasSadddle
    • LivingEntity
      • timeOffsrotOffs
      • rotA
      • oRunrun
      • animStepanimStep0
      • appliedScale
      • canBeNameTagged
    • Mob
      • DEFAULT_EQUIPMENT_DROP_CHANCE
      • PRESERVE_ITEM_DROP_CHANCE_THRESHOLDPRESERVE_ITEM_DROP_CHANCE
    • NeutralMob#setLastHurtByPlayer
    • PositionMoveRotation#ofEntityUsingLerpTarget
  • net.minecraft.world.entity.ai.attributes.AttributeModifier#saveload
  • net.minecraft.world.entity.animal
    • Dolphin#setTreasurePosgetTreasurePos
    • Fox$Variant#byName
    • MushroomCow$Variant#byName
    • Panda$Gene#byName
    • Salmon$Variant#byName
    • Turtle
      • getHomePos
      • setTravelPosgetTravelPos
      • isGoingHomesetGoingHome
      • isTravellingsetTravelling
  • net.minecraft.world.entity.animal.armadillo.Armadillo$ArmadilloState#fromName
  • net.minecraft.world.entity.npc.VillagerTrades#EXPERIMENTAL_WANDERING_TRADER_TRADES
  • net.minecraft.world.entity.projectile.AbstractArrow#getBaseDamage
  • net.minecraft.world.entity.raid.Raid
    • getLevelgetId
    • save
  • net.minecraft.world.entity.vehicle.AbstractMinecart#hasCustomDisplaysetCustomDisplay
  • net.minecraft.world.item.ItemStack#parseOptionalsaveOptional
  • net.minecraft.world.item.equipment.trim.TrimPattern#templateItem
  • net.minecraft.world.level.Level#updateNeighborsAt(BlockPos, Block)
  • net.minecraft.world.level.block.entity
    • CampfireBlockEntity#dowse
    • PotDecorations#saveload
  • net.minecraft.world.level.levelgen.BelowZeroRetrogen#read
  • net.minecraft.world.level.levelgen.structure.structures.RuinedPortalPiece$VerticalPlacement#byName
  • net.minecraft.world.level.saveddata.maps.MapBanner#LIST_CODEC
  • net.minecraft.world.scores.Team
    • $CollisionRule#byName
    • $Visibility#getAllNamesbyName
  • net.minecraft.world.ticks.LevelChunkTicks#saveload

Minecraft 1.21.5 -> 1.21.6 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

感谢:

  • @Soaryn 提供了一些 ItemStack 最佳实践和拼写修复
  • @earthcomputer 提供了绘制字符串时的颜色更改

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

GUI 变更

GUI 渲染系统与之前的版本相比发生了重大变化。虽然表面上看起来有些相似,但实际的实现细节要复杂得多且迂回。本文将以高层次概述新系统,并提供一些基本示例。

准备与渲染

渲染 GUI 已分为两个阶段:“准备”和“渲染”。

准备阶段是我们通常认为的 GUI 渲染方法(例如,Gui#renderAbstractContainerScreen#renderBg 等)。这些方法现在不再实际渲染组件,而是将它们提交给 GuiRenderState 以存储在“渲染”阶段使用。GuiRenderState 存储在 GameRenderer 上,并传递给 GuiGraphics,后者使用前述方法将所需对象添加到渲染状态。

渲染阶段实际处理所有对象的渲染。这是通过 GuiRenderer 处理的,它从 GuiRenderState 读取数据,并在经过一些委托的准备和排序后,将对象渲染到屏幕上。GuiRenderer 也存储在 GameRenderer 上。

元素排序

现在,元素是如何渲染到屏幕上的?在之前的版本中,这主要基于渲染调用的顺序。然而,新系统使用两种不同的排序方法。第一种方法使用层和线性树来处理深度。第二种方法基于三个因素(按优先级顺序)使用比较器:ScreenRectangle 剪裁、RenderPipeline 顺序和 TextureSetup 的哈希码。这些都存储在通过 GuiRenderState#submitGuiElement 传递给 GuiRenderStateGuiElementRenderState 上。

一旦元素排序完毕,它们将从 Z 值为 0 开始渲染,每个元素比前一个元素向前渲染 0.01

作为警告,由于元素排序顺序,某些自定义配置可能导致屏幕渲染不正确。因此,您必须理解这些方法及其分配的值在排序元素时的工作原理。

层与树

第一种排序方法处理对象渲染的 z 深度。

首先从线性树开始。顾名思义,它基本上是一个双向链接的 GuiRenderState$Node 列表。每个节点包含自己的要渲染的元素列表。使用 GuiRenderState#updown 来导航节点列表,每个方法要么获取下一个节点,要么如果不存在则创建一个新节点。给定树中的节点从底部到顶部渲染,这意味着 down 将在当前节点之前渲染任何提交的元素,而 up 将在当前节点之后渲染任何提交的元素。

提交元素时,使用其 ScreenArea 自动计算元素被添加到哪个节点。ScreenArea 定义了要渲染的元素的 bounds。本质上,如果元素的边界与当前节点上的任何其他元素相交,则将在 up 方向添加一个节点。

然后是层(strata)。一个层本质上是一个线性树。层按照它们被创建的顺序渲染,这意味着调用 nextStratum 将在前一层之后渲染所有元素。如果您想将元素分组到特定层中,可以使用此功能。注意:您无法导航到之前的层。

比较器

比较器处理层中线性树内给定节点中的元素排序。

屏幕矩形剪裁

ScreenRectangle 就是允许元素绘制的区域,通过 GuiElementRenderState#scissorArea 存储。没有指定 ScreenRectangle 的元素将首先排序,然后是最小 Y、最大 Y、最小 X 和最大 X。

渲染管线

RenderPipeline 定义了用于将某些对象渲染到屏幕的管线,包括其着色器、格式、统一变量等。这通过 GuiElementRenderState#pipeline 存储。管线按照它们构建的顺序排序。这意味着,如果在同一层和剪裁矩形上,RenderPipelines#ENTITY_TRANSLUCENT 将在 RenderPipelines#GUI 之前渲染。由于这是一个依赖于类加载常量的系统,如果您想添加新元素,请确保您的模组加载器支持某种动态管线排序。

纹理哈希码

TextureSetup 定义了在渲染管线中使用的 Sampler0Sampler1Sampler2,通过 GuiElementRenderState#textureSetup 存储。没有纹理的元素将首先排序,然后是记录对象的 getSortKey。注意,目前这返回 TextureSetuphashCode,由于 GpuTextureView 不实现 hashCode,而是依赖于身份对象哈希,这可能是不确定的。

GuiElementRenderState

现在我们理解了排序,我们一直在使用的 GuiElementRenderState 到底是什么?实际上,渲染到屏幕的每个对象都由一个 GuiElementRenderState 表示,从库存菜单中看到的玩家到每个单独的物品。一个 GuiElementRenderState 定义了四个方法。首先,是用于排序以及如何渲染到屏幕的常用方法(pipelinescissorAreatextureSetupbounds)。然后是 buildVertices,它接受 VertexConsumer 来写入顶点和 z 深度。对于 GUI,这通常调用 VertexConsumer#addVertexWith2DPose

原版提供了三种类型的 GuiElementRenderStateBlitRenderStateColoredRectangleRenderStateGlyphEffectRenderStateGlyphRenderStateColoredRectangleRenderStateGlyphRenderState/GlyphEffectRenderState 分别是处理基本颜色矩形和文本字符的简单情况。BlitRenderState 覆盖所有其他情况,因为几乎所有方法最终都会写入一个 GpuTexture,然后由它消费。

GuiElementRenderState 通过 GuiRenderState$Node#submitGuiElement 添加到 GuiRenderStateGuiRenderState 使 submitBlitToCurrentLayersubmitGlyphToCurrentLayer 可用于添加纹理和字形。例如,这些由 GuiGraphics#*linefillblit* 方法调用。

GuiItemRenderState

GuiItemRenderState 是一个特殊情况,用于将物品渲染到屏幕。它接受物品的字符串化名称、当前姿势、其 XY 坐标及其剪裁区域。它持有的 ItemStackRenderState 定义了物品的渲染方式。当 ClientItem$Properties#oversizedInGui 为 true 时,渲染边界基于物品模型边界框计算;否则,当为 false 时,使用 16x16 的正方形。

就在“渲染”阶段之前,GuiRenderer 有效地将 GuiItemRenderState 转换为 GuiElementRenderState,更具体地说是 BlitRenderState。这是通过构造一个物品图集 GpuTexture 来完成的,物品被绘制到该纹理上,然后该纹理作为 BlitRenderState 提交。所有 GuiItemRenderState 都使用 RenderPipelines#GUI_TEXTURED_PREMULTIPLIED_ALPHA

GuiElementRenderState 通过 GuiRenderState#submitItem 添加到 GuiRenderState。这由 GuiGraphics#render*Item* 方法调用。

GuiTextRenderState

GuiTextRenderState 是一个特殊情况,用于将文本渲染到屏幕。它接受 FontFormattedCharSequence、当前姿势、其 XY 坐标、颜色、背景颜色、是否有阴影及其渲染边界。

就在“渲染”阶段之前,GuiRendererGuiTextRenderState 转换为 GuiElementRenderState,更具体地说是 GlyphRenderStateGlyphEffectRenderState,具体取决于通过 GuiTextRenderState#ensurePrepared 应渲染的内容。这执行与物品渲染状态类似的过程,其中文本被写入 GpuTexture 以供消费。任何背景首先被渲染,然后是背景效果,然后是字符,最后是前景效果。

GuiElementRenderState 通过 GuiRenderState#submitText 添加到 GuiRenderState。这由 GuiGraphics#draw*Stringrender*Tooltip 方法调用。

画中画

画中画是一个特殊情况,用于将任意对象渲染到 GpuTexture,然后传递给 BlitRenderState。画中画由两个组件组成:PictureInPictureRenderStatePictureInPictureRenderer

PictureInPictureRenderState 是一个接口,可以存储一些用于将对象渲染到纹理的数据。默认情况下,它必须提供最小和最大 XY 坐标、纹理缩放、其剪裁区域及其渲染边界。您还可以选择通过 pose 指定变换矩阵。任何其他数据都可以由实现者添加。

public record ExamplePIPRenderState(boolean data, int x0, int x1, int y0, int y1, float scale, @Nullable ScreenRectangle scissorArea, @Nullable ScreenRectangle bounds)
    implements PictureInPictureRenderState {}

PictureInPictureRenderer 是将数据写入 GpuTexture 的渲染器。它利用这样一个事实:如果 RenderSystem#output*Override 纹理不为 null,则它们会被写入 BufferSource。一个 PictureInPictureRenderer 方法必须实现三个方法。getRenderStateClass 返回 PictureInPictureRenderState 实现的类。getTextureLabel 返回用于调试的纹理标签。renderToTexture 是调用渲染逻辑以将数据写入纹理的地方。

public class ExamplePIPRenderer extends PictureInPictureRenderer<ExamplePIPRenderState> {

    // 接受来自 `RenderBuffers` 的缓冲区源
    public ExamplePIPRenderer(MultiBufferSource.BufferSource bufferSource) {
        super(bufferSource);
    }

    @Override
    public Class<ExamplePIPRenderState> getRenderStateClass() {
        // 渲染状态的类
        return ExamplePIPRenderState.class;
    }

    @Override
    protected void renderToTexture(ExamplePIPRenderState renderState, PoseStack pose) {
        // 在此处渲染您想要的任何内容
        // 您可以通过 `this.bufferSource` 使用缓冲区源
    }

    @Override
    protected void blitTexture(ExamplePIPRenderState renderState, GuiRenderState guiState) {
        // 如果您想更改图层提交到渲染状态的方式,可以覆盖此方法
        // 默认情况下,这使用 `BlitRenderState`

        // 如果您想自己处理提交,请删除此项
        super.blitTexture(renderState, guiState);
    }

    @Override
    protected boolean textureIsReadyToBlit(ExamplePIPRenderState renderState) {
        // 当为 true 时,将跳过设置纹理和投影矩阵,并使用当前可用的任何内容
        return false;
    }

    @Override
    protected String getTextureLabel() {
        // 这可以是任何内容,但应该是唯一的
        return "examplemod: example pip";
    }
}

要能够使用渲染器,必须将其添加到 GuiRenderer#pictureInPictureRenderers。由于构造函数接受一个不可变列表,而渲染器存储一个不可变映射,请使用您的模组加载器提供的任何方法。

// 我们将假设:
// - `GuiRenderer#bufferSource` 是可访问的
// - 映射是可变的
// 对于某个 GuiRenderer renderer

var examplePIP = new ExamplePIPRenderer(renderer.bufferSource);

renderer.pictureInPictureRenderers.put(
    examplePIP.getRenderStateClass(),
    examplePIP
);

PictureInPictureRenderState 通过 GuiRenderState#submitPicturesInPictureState 添加到 GuiRenderState。这由 GuiGraphics#submit*RenderState 方法调用。

逻辑变更

GuiGraphics#drawString 现在允许 int 颜色参数接受 alpha 通道(高八位),从而与其他 GuiGraphics 方法保持一致。这意味着任何没有指定 alpha 的颜色字符串将不会被渲染。可以通过将您的 int 颜色与 0xFF000000 进行 OR 操作,或者将您的颜色传递给 ARGB#opaque 来复制以前的行为。

上下文栏

屏幕上的许多 HUD 元素会占据经验条渲染的位置。然而,这些元素如何渲染以及哪个元素被优先考虑是通过上下文栏系统处理的。一个上下文栏由两部分组成:ContextualBarRenderer,负责将栏渲染到屏幕;以及 Gui$ContextualInfo,用作栏的标识符。

一个 ContextualBarRenderer 需要实现两个方法:renderBackground,用于渲染栏本身;以及 render,用于渲染出现在栏顶部的元素。

public class ExampleContextualBarRenderer implements ContextualBarRenderer {

    @Override
    public void renderBackground(GuiGraphics graphics, DeltaTracker delta) {
        // 在此处渲染背景栏精灵
    }

    @Override
    public void render(GuiGraphics graphics, DeltaTracker delta) {
        // 渲染任何可能位于栏顶部的元素
    }
}

Gui$ContextInfo 是一个枚举,因此您的模组加载器需要允许扩展或某种其他方法来标识栏渲染器。然后,需要将渲染器添加到存储在 Gui#contextualInfoBarRenderers 中的渲染器映射中。由于这是一个不可变映射,请使用您的模组加载器提供的任何方法。

// 我们将假设:
// - 创建了一个新的枚举值 `EXAMPLEMOD_EXAMPLE`
// - 映射是可变的
// 对于某个 Gui gui
gui.contextualInfoBarRenderers.put(
    EXAMPLEMOD_EXAMPLE,
    ExampleContextualBarRenderer::new
);

最后,为了让您的栏被调用并优先考虑,您需要修改 Gui#nextContextualInfoState 以返回您的枚举值,或者使用您的模组加载器提供的任何方法。

对话框

为了更通用地处理提供某些基本功能的屏幕——例如确认屏幕、按钮选择或用户输入,原版提供了一个通用的对话框系统。这些对话框可以在数据包中构建,并通过调用 Player#openDialog 在客户端上传递。基本的 JSON 描述记录在 Minecraft Snapshot 25w20a 中。

快速概述,一个基本的 Dialog 包含以下组件:一个标题、一个可选的用于导航的外部标题、是否可以通过按“esc”关闭屏幕,以及它的 DialogBody 内容。其他所有内容由对话框本身决定,但它具有通过 InputControl 进行用户输入的功能。按钮通常通过 ClickAction 添加,它包含常见的按钮数据和点击时要执行的事件。如果对话框被取消(例如,关闭),则运行 onCancel

DialogBodyInputControl 只是没有定义结构的通用接口。实现它们,或者任何对话框,都需要在客户端和服务器上向可用类型进行一些注册。

自定义主体

一个 DialogBody 就是对话框屏幕的内容。这通常是应该始终显示的不可变信息。每个对话框都持有一个这些 DialogBody 的列表,因为每个屏幕都有一些文本来解释它的用途。它只包含一个方法 mapCodec,用作主体信息的注册表键和编码器。

// 显然,一个主体会有实际内容,但这只是一个示例实现
public record ExampleDialogBody(boolean val1, int val2) implements DialogBody {
    public static final MapCodec<ExampleDialogBody> BODY_CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        Codec.BOOL.fieldOf("val1").forGetter(ExampleDialogBody::val1),
        Codec.INT.fieldOf("val2").forGetter(ExampleDialogBody::val2)
    ).apply(ExampleDialogBody::new));

    @Override
    public MapCodec<? extends DialogBody> mapCodec() {
        return BODY_CODEC;
    }
}

// 将编解码器注册到注册表
Registry.register(BuiltInRegistries.DIALOG_BODY_TYPE, "examplemod:example_body", ExampleDialogBody.BODY_CODEC);
// 对于某个对话框
{
    // ...
    "body": [
        {
            // 我们的主体
            "type": "examplemod:example_body",
            "val1": true,
            "val2": 0
        },
        // ...
    ]
}

那么这个主体实际上是如何渲染的呢?这是通过 DialogBodyHandler 完成的。它包含一个单一方法 createControls,用于生成给定 DialogScreen 和对话框数据的 LayoutElement 进行渲染。这个主体处理程序可以通过 DialogBodyHandlers#register 链接到 MapCodec

public class ExampleDialogBodyHandler implements DialogBodyHandler<ExampleDialogBody> {

    @Override
    public LayoutElement createControls(DialogScreen<?> screen, ExampleDialogBody body) {
        // 创建元素(小部件、布局等)
        return new StringWidget(...);
    }
}

// 注意 `register` 不是公开的,因此需要访问扩宽
DialogBodyHandlers.register(BODY_CODEC, new ExampleDialogBodyHandler());

自定义输入

一个 InputControl 表示用户可以提供的某些输入,无论是文本还是按钮提交点击。这通常由可以根据状态接受或提供某些字符串值或标签的组件组成。所有对话框都可以通过 DialogControlSet 提供这些输入。它只包含一个方法 mapCodec,用作输入控件的注册表键和编码器。

public record ExampleInputControl(int value) implements InputControl {
    public static final MapCodec<ExampleInputControl> INPUT_CODEC = Codec.INT.fieldOf("value").xmap(
        ExampleInputControl::new, ExampleInputControl::value
    );

    @Override
    public MapCodec<? extends InputControl> mapCodec() {
        return INPUT_CODEC;
    }
}

// 将编解码器注册到注册表
Registry.register(BuiltInRegistries.INPUT_CONTROL_TYPE, "examplemod:example_input", ExampleInputControl.INPUT_CODEC);
// 对于某个对话框(假设 `minecraft:simple_input_form`)
{
    "inputs": [
        {
            // 我们的输入
            "type": "examplemod:example_input",
            
            // 此输入数据的标识符
            "key": "example_input",

            "value": 0
        },
        // ...
    ]
}

与上面一样,输入通过 InputControlHandler 渲染。它包含一个单一方法 addControl,提供 Screen 和输入控件,并通过 $Output 创建 LayoutElement 及其关联的 Action$ValueGetter。这个输入处理程序可以通过 InputControlHandlers#register 链接到 MapCodec

public class ExampleInputControlHandler implements InputControlHandler<ExampleInputControl> {

    @Override
    public void addControl(ExampleInputControl control, Screen screen, InputControlHandler.Output output) {
        EditBox box = new EditBox(...);
        box.setValue(String.valueOf(control.value()));

        // 将元素添加到输出
        output.accept(
            // 要渲染的元素
            box,
            // 输入的值输出
            Action.ValueGetter.of(box::getValue)
        );
    }
}

// 注意 `register` 不是公开的,因此需要访问扩宽
InputControlHandlers.register(INPUT_CODEC, new ExampleInputControlHandler());

自定义动作

如上所示,输入可以提供一些值传递给 Action。前者被称为 $ValueGetter,它基本上获取一个字符串化或标记的输入以供使用。后者则最终创建发送到服务器的 ClickEvent。这些通常通过 ActionButton 创建,它定义了一些常见的按钮数据以及要执行的 Action

一个自定义动作包含两个方法:一个返回在编码期间使用的 MapCodeccodec),另一个根据输入字符串到其 $ValueGetter 的映射创建 ClickEvent

public record ExampleAction() implements Action {
    public static final MapCodec<ExampleAction> ACTION_CODEC = MapCodec.unit(new ExampleAction());

    @Override
    public MapCodec<? extends Action> codec() {
        return ACTION_CODEC;
    }

    @Override
    public Optional<ClickEvent> createAction(Map<String, Action.ValueGetter> keysToGetters) {
        // 处理如何将键输入映射映射到某个点击事件
        return Optional.empty();
    }
}

// 将编解码器注册到注册表
Registry.register(BuiltInRegistries.DIALOG_ACTION_TYPE, "examplemod:example_action", ExampleAction.ACTION_CODEC);
// 对于某个对话框(假设 `minecraft:notice`)
{
    "action": {
        // 按钮数据
        "label": "示例!",
        "tooltip": "这是一个示例!",
        "width": 80,

        // 要执行的动作
        "action": {
            // 我们的动作类型
            "type": "examplemod:example_action"
        }
    }
}

根据您在下面实现 Dialog 的方式,动作按钮将自动添加到屏幕,或者您需要通过 DialogControlSet#createActionButton 在其中一个方法中添加它:

// 对于某个 DialogScreen 实现,我们假设某个 `SimpleDialog`
@Override
protected void updateHeaderAndFooter(HeaderAndFooterLayout layout, DialogControlSet controls, SimpleDialog dialog, DialogConnectionAccess access) {
    dialog.mainActions().forEach(actionButton -> layout.addToFooter(controls.createActionButton(actionButton).build()));
}

自定义对话框

一个 Dialog 基本上就是上述所有组件的组合,按需组合。由用户决定如何实现它们。每个 Dialog 必须提供其 CommonDialogData,它定义了基本标题、主体内容和功能。此外,一个 Dialog 可以选择在关闭时通过 onCancel 执行一个 Action

// `common` 已由记录实现
public record ExampleDialog(CommonDialogData common, boolean val1, int val2) implements Dialog {
    public static final MapCodec<ExampleDialog> DIALOG_CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        CommonDialogData.MAP_CODEC.forGetter(ExampleDialog::common),
        Codec.BOOL.fieldOf("val1").forGetter(ExampleDialog::val1),
        Codec.INT.fieldOf("val2").forGetter(ExampleDialog::val2)
    ).apply(ExampleDialog::new));

    @Override
    public MapCodec<? extends Dialog> codec() {
        return DIALOG_CODEC;
    }

    @Override
    public Optional<Action> onCancel() {
        // 您可以选择在此处返回一些内容,或者如果什么都不做则返回空
        return Optional.empty();
    }
}

// 将编解码器注册到注册表
Registry.register(BuiltInRegistries.DIALOG_TYPE, "examplemod:example_dialog", ExampleDialog.DIALOG_CODEC);
// 对于 `data/examplemod/dialog/example.json` 中的某个对话框
{
    // 我们的对话框类型
    "type": "examplemod:example_dialog",
    
    // 常见按钮数据
    "title": "示例对话框!",
    "can_close_with_escape": true,
    "after_action": "wait_for_response",

    // 我们的自定义参数
    "val1": true,
    "val2": 0
}

与其他一样,对话框类型只能通过 DialogScreen$Factory 渲染。这个接口构造一个 DialogScreen,给定父 ScreenDialog 实例和用于与服务器通信的 DialogConnectionAccess。然后可以通过 DialogScreens#register 将这个对话框屏幕链接到 MapCodec

public class ExampleDialogScreen extends DialogScreen<ExampleDialog> {

    public ExampleDialogScreen(@Nullable Screen previousScreen, ExampleDialog dialog, DialogConnectionAccess connectionAccess) {
        super(previousScreen, dialog, connectionAccess);
    }

    // 您可以根据需要选择实现其他方法
    // 有关示例,请参阅现有的对话框屏幕

    @Override
    protected void populateBodyElements(LinearLayout layout, DialogControlSet controls, ExampleDialog dialog, DialogConnectionAccess access) {
        // 将元素和动作添加到屏幕的主体(通常是中心)
    }

    @Override
    protected void updateHeaderAndFooter(HeaderAndFooterLayout layout, DialogControlSet controls, ExampleDialog dialog, DialogConnectionAccess access) {
        // 将元素和动作添加到屏幕的页眉和页脚(顶部和底部)
    }
}

// 注意 `register` 不是公开的,因此需要访问扩宽
DialogScreens.register(DIALOG_CODEC, ExampleDialogScreen::new);
  • com.mojang.blaze3d.vertex.VertexConsumer#addVertexWith2DPose - 添加一个要在 2D 空间中渲染的顶点。
  • net.minecraft.client.gui
    • Font
      • drawInBatch 不再返回任何内容
      • prepareText - 准备要渲染到屏幕的文本。
      • splitIgnoringLanguage - 按提供的顺序拆分文本,而不经过语言处理程序处理。
      • ALPHA_CUTOFF 已移除
      • $GlyphVisitor - 一个处理要渲染的字形或效果的接口。
      • $PreparedText - 一个接口,通过访问每个字形来定义应如何渲染一段文本。
      • $StringRenderOutput -> $PreparedTextBuilder,不再接受 MultiBufferSourceMatrix4f$DisplayMode、打包的光照坐标和逆深度布尔值
    • Gui
      • shouldRenderDebugCrosshair - 如果应渲染调试准星,则返回 true。
      • $RenderFunction - 一个接口,定义如何在 GUI 上渲染某个部分或元素。
    • GuiGraphics 现在接受一个 GuiRenderState 而不是 MultiBufferSource$BufferSource
      • MAX_GUI_ZMIN_GUI_Z 已移除
      • pose 现在返回一个 Matrix3x2fStack
      • flush 已移除
      • nextStratum - 添加另一个层,用于遍历在先前树中的所有节点之后渲染。
      • 所有方法不再接受 RenderTypeVertexConsumerFunction<ResourceLocation, RenderType>,而是根据调用指定 RenderPipelineTextureSetup
      • drawStringdrawStringWithBackdrop 不再返回任何内容
      • draw*String 方法现在必须传入一个 ARGB 值,其中 A 不能为 0。
      • renderItem(ItemStack, int, int, int, int) 已移除
      • drawSpecial 已移除,根据特殊情况由单独的 submit*RenderState 取代
      • blurBeforeThisStratum - 通知渲染状态,模糊效果应在该层和所有先前渲染的层之间渲染。每帧只能应用一次。
      • render*Tooltip -> set*TooltipForNextFrame,不直接添加到渲染状态,而是在不存在或被覆盖时等待调用 renderDeferredTooltip
      • renderDeferredTooltip - 添加要在新层上渲染的工具提示信息。
      • blitSprite 现在有一个接受浮点 R 色调颜色的重载
      • $ScissorStack#peek - 获取堆栈上的最后一个矩形。
    • LayeredDraw 类已移除
  • net.minecraft.client.gui.components
    • AbstractTextAreaWidget 现在有一个重载,接受两个额外的布尔值,表示是否显示背景或装饰
    • AbstractWidget#getTooltip 已移除
    • CycleButton$Builder#displayOnlyValue 现在有一个接受 boolean 设置的重载
    • EditBox
      • setCentered - 设置文本位置是否应居中。
      • setTextShadow - 设置文本是否应有阴影效果。
    • FocusableTextWidget 现在可以接受一个布尔值,表示是否填充背景
      • DEFAULT_PADDING 现在是公开的
    • ImageWidget#updateResource - 更新组件上图像的精灵。
    • ItemDisplayWidget - 一个显示 ItemStack 的小部件。
    • LogoRenderer#keepLogoThroughFade - 当为 true 时,即使标题屏幕淡出,也保持徽标可见。
    • MultiLineEditBox 现在是包私有的,应通过 builder 构造,调用 $Builder#set* 方法
      • setLineLimit - 设置文本字段的行限制。
      • setValue 现在有一个接受 boolean 的重载,用于确定是否应强制通过最大行限制
    • MultiLineLabel
      • getStyleAtCentered - 计算居中文本的组件样式。
      • getStyleAtLeftAligned - 计算左对齐文本的组件样式。
    • MultilineTextField#NO_CHARACTER_LIMIT -> NO_LIMIT
      • setLineLimit - 设置文本字段上可以写入的最大行数。
      • hasLineLimit - 返回文本字段是否有行限制。
      • setValue 现在有一个接受 boolean 的重载,用于确定是否应强制通过最大行限制
    • MultiLineTextWidget#configureStyleHandling - 设置在悬停组件时是否显示某些内容以及点击时的操作。
    • ScrollableLayout - 一个具有某些定义边界并且可以滚动的布局。
    • SplashRenderer#render 现在接受一个浮点数作为 R 颜色,而不是 int
    • WidgetTooltipHolder#refreshTooltipForNextRenderPass 现在接受 GuiGraphics 和 XY 位置
  • net.minecraft.client.gui.components.spectator.SpectatorGui#renderTooltip -> renderAction
  • net.minecraft.client.gui.components.tabs
    • LoadingTab - 一个表示当前正在加载信息的标签页。
    • Tab#getTabExtraNarration - 返回标签页的提示旁白。
    • TabManager 现在可以接受两个 Consumer,用于在选中或取消选中标签页时执行的操作
    • TabNavigationBar
      • getTabs - 返回导航栏上的标签页列表。
      • setTabActiveState - 设置给定标签页索引的活动状态。
      • setTabTooltip - 设置给定标签页索引的工具提示信息。
  • net.minecraft.client.gui.components.toasts
    • NowPlayingToast - 一个显示当前正在播放的背景音乐的吐司。
    • Toast
      • xPosyPos - 获取相对于当前吐司索引的 x 和 y 位置。
      • onFinishedRendering - 吐司在屏幕上完成渲染后调用的方法。
    • ToastManager 现在接受 Options
      • showNowPlayingToasthideNowPlayingToastcreateNowPlayingToastremoveNowPlayingToast - 处理“正在播放”音乐吐司。
      • $ToastInstance#resetToast - 重置吐司。
  • net.minecraft.client.gui.contextualbar
    • ContextualBarRenderer - 一个接口,定义了一个具有某些要渲染的背景的对象。
    • ExperienceBarRenderer - 绘制经验条。
    • JumpableVehicleBarRenderer - 绘制跳跃力量条(例如,马跳跃)。
    • LocatorBarRenderer - 绘制指向给定路径点的条。
  • net.minecraft.client.gui.font.GlyphRenderTypes 现在接受一个用于 GUI 渲染的 RenderPipeline
  • net.minecraft.client.gui.font.glyphs.BakedGlyph 现在接受一个 GpuTextureView
    • extractEffect - 提取一个字形效果(例如阴影)并提交要渲染的元素。
    • extractBackground - 提取一个字形效果并提交要在背景 Z 上渲染的元素。
    • lefttoprightbottom - 计算字形的边界。
    • textureView - 返回构成字形的纹理视图。
    • guiPipeline - 返回渲染字形的管线。
    • renderCharrenderEffect 现在接受一个额外的布尔值,当为 true 时将 Z 偏移设置为 0,为 false 时设置为 0.001
    • $Effect#lefttoprightbottom - 计算字形效果的边界。
    • $GlyphInstance#lefttoprightbottom - 计算字形实例的边界。
  • net.minecraft.client.gui.navigation.ScreenRectangle
    • transformAxisAligned 现在接受 Matrix3x2f 而不是 Matrix4f
    • intersects - 返回此矩形是否与另一个矩形重叠。
    • encompasses - 返回此矩形是否完全包含另一个矩形。
    • transformMaxBounds - 返回一个新矩形,该矩形通过提供的矩阵移动到给定位置。
  • net.minecraft.client.gui.render
    • GuiRenderer - 一个将所有提交的元素渲染到屏幕的类。
    • TextureSetup - 一个记录,指定在渲染管线中使用的采样器 0-2。前两个纹理视图是任意的,第三个用于当前的光照图纹理。
  • net.minecraft.client.gui.render.pip
    • GuiBannerResultRenderer - 旗帜结果预览的渲染器。
    • GuiBookModelRenderer - 附魔屏幕中书模型的渲染器。
    • GuiEntityRenderer - 给定实体的渲染器。
    • GuiProfilerChartRenderer - 分析器图表的渲染器。
    • GuiSignRenderer - 编辑屏幕中告示牌背景的渲染器。
    • GuiSkinRenderer - 具有给定皮肤的玩家的渲染器。
    • OversizedItemRenderer - 用于物品模型应渲染得比其物品槽位大时的渲染器。
    • PictureInPictureRenderer - 一个抽象类,用于渲染非标准 2D 元素、物品或文本的动态元素。
  • net.minecraft.client.gui.render.state
    • BlitRenderState - 用于基本 2D 纹理 blit 的元素状态。
    • ColoredRectangleRenderState - 用于带有色调的简单矩形的元素状态。
    • GlyphEffectRenderState - 用于字形效果(例如,字体文本阴影)的元素状态。
    • GlyphRenderState - 用于字形(字体文本)的元素状态。
    • GuiElementRenderState - 一个表示要渲染的元素状态的接口。
    • GuiItemRenderState - 一个表示要渲染的物品状态的记录。
    • GuiRenderState - 要渲染到屏幕的 GUI 的状态。
    • GuiTextRenderState - 一个表示文本及其渲染位置的记录。
    • ScreenArea - 一个定义元素渲染区域的接口。这不会影响剪裁,而是影响层顺序。
  • net.minecraft.client.gui.render.state.pip
    • GuiBannerResultRenderState - 旗帜结果预览的状态。
    • GuiBookModelRenderState - 附魔屏幕中书模型的状态。
    • GuiEntityRenderState - 给定实体的状态。
    • GuiProfilerChartRenderState - 分析器图表的状态。
    • GuiSignRenderState - 编辑屏幕中告示牌背景的状态。
    • GuiSkinRenderState - 具有给定皮肤的玩家的状态。
    • OversizedItemRenderState - 可以以任意大小渲染的物品模型的状态。
    • PictureInPictureRenderState - 一个定义将画中画渲染到屏幕所需基本状态的接口。
  • net.minecraft.client.gui.screens
    • ConfirmScreen
      • layout - 定义一个由八个单位间隔的垂直元素列表。
      • yesButtonnoButton -> yesButtonComponentnoButtonComponent
        • yesButtonnoButton 现在表示实际的按钮
      • addAdditionalText - 在布局中的按钮之前添加任何附加文本。
      • addButtons - 在布局中添加按钮。
    • PauseScreen
      • rendersNowPlayingToast - 返回是否应渲染“正在播放”吐司。
      • onDisconnect -> disconnectFromWorld,现在是公开和静态的;不是一对一
    • Screen
      • CUBE_MAP -> net.minecraft.client.renderer.GameRenderer#cubeMap
      • PANORAMA -> net.minecraft.client.renderer.GameRenderer#panorama
      • renderBlurredBackground 现在接受 GuiGraphics
      • *TooltipForNextRenderPass 方法要么已移除,要么移至 GuiGraphics
      • FADE_IN_TIME - 表示某个元素淡入需要多少毫秒。
      • fadeWidgets - 设置作为屏幕子级添加的 AbstractWidget 的 alpha 值。
      • handleClickEvent - 处理点击组件时要播放的事件。
      • defaultHandleClickEvent - 点击组件时要执行的默认逻辑。
      • clickUrlAction - 点击 URL 时要执行的逻辑(具有打开 URL 样式)。
      • clickCommandAction - 应执行命令时要执行的逻辑(具有 * 命令样式)。
  • net.minecraft.client.gui.screens.dialog
    • ButtonListDialogScreen - 一个包含一些按钮列表的对话框屏幕。
    • DialogConnectionAccess - 一个处理来自对话框的通用交互信息的客户端接口。
    • DialogControlSet - 对话框屏幕的输入处理程序。
    • DialogListDialogScreen - 一个指向其他对话框的按钮列表的 DialogListDialog
    • DialogScreen - 某个对话框模态的屏幕。
    • DialogScreens - 对话框模态到其关联屏幕的工厂注册表。
    • MultiButtonDialogScreen - 一个 MultiActionDialog 的按钮列表。
    • ServerLinksDialogScreen - 一个 ServerLinksDialog 的按钮列表。
    • SimpleDialogScreen - 某个简单对话框的对话框屏幕。
    • WaitingForResponseScreen - 处理客户端/服务器之间对话框提交的停机时间的屏幕。
  • net.minecraft.client.gui.screens.dialog.body
    • DialogBodyHandler - 描述标题和动作/输入之间内容的主体元素列表。
    • DialogBodyHandlers - DialogBody 到其 DialogBodyHandler 的注册表。
  • net.minecraft.client.gui.screens.dialog.input
    • InputControlHandler - 用户输入处理程序。
    • InputControlHandlers- InputControl 到其 InputControlHandler 的注册表。
  • net.minecraft.client.gui.screens.inventory
    • AbstractContainerScreen
      • SLOT_ITEM_BLIT_OFFSET 已移除
      • renderContents - 渲染库存的槽位和标签。
      • renderCarriedItem - 渲染持有的物品。
      • renderSnapbackItem - 渲染与持有物品交换的物品。
      • $SnapbackData - 保存关于拖拽或交换物品从持有位置移动到其槽位位置的信息。
    • AbstractSignEditScreen#offsetSign -> getSignYOffset,不是一对一
    • BookEditScreen
      • TEXT_*IMAGE_*BACKGROUND_TEXTURE_* 现在是公开的
    • BookSignScreen - 用于签署书的屏幕。
    • BookViewScreen
      • closeScreen -> closeContainerOnServer,不是一对一
      • $BookAccess#getPage 现在返回一个 Component
    • EffectsInInventory
      • renderEffects 现在是公开的
      • renderTooltip 已被重载为一个公共方法
    • InventoryScreen#renderEntityInInventory 不再接受 XY 偏移,而是接受 4 个 int 来表示要渲染到的区域
    • ItemCombinerScreen#renderFg 已移除
  • net.minecraft.client.gui.screens.inventory.tooltip
    • ClientTooltipComponent#renderText 不再接受姿势和缓冲区,而是接受 GuiGraphics 来提交要渲染的文本
    • TooltipRenderUtil#renderTooltipBackground 不再接受 Z 偏移
  • net.minecraft.client.gui.screens.multiplayer.ServerLinksScreen 类已移除,被对话框模态取代
  • net.minecraft.client.gui.screens.social
    • PlayerEntry#refreshHasDraftReport - 设置当前上下文是否具有针对此玩家的报告。
    • SocialInteractionsPlayerList#refreshHasDraftReport - 刷新当前上下文是否对所有玩家有报告。
  • net.minecraft.client.gui.screens.worldselection.ExperimentsScreen$ScrollArea 类已移除,被 ScrollableLayout 取代
  • net.minecraft.client.model.geom.ModelPart#getExtentsForGui - 获取表示已变换到适当空间的部件的向量集。
  • net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl
    • showDialog - 显示当前对话框,动态创建屏幕。
    • serverLinks - 返回客户端可以访问的服务器链接条目。
    • createDialogAccess - 创建用于通信的客户端对话框处理程序。
    • clearDialog - 关闭当前对话框屏幕。
  • net.minecraft.client.player.LocalPlayer#experienceDisplayStartTick - 表示经验显示应被优先考虑的开始刻。
  • net.minecraft.client.renderer
    • GameRenderer 不再接受 ResourceManager
      • ITEM_ACTIVATION_ANIMATION_LENGTH 已移除
      • setRenderHand 已移除
      • renderZoomed 已移除
      • getPanorama - 返回全景渲染器。
    • LightTexture#getTexture -> getTextureView,不是一对一
    • MapRenderer#WIDTHHEIGHT 现在是公开的
    • PanoramaRenderer#registerTextures - 注册纹理以供立方体贴图使用。
    • PostPass$Input#texture 现在返回 GpuTextureView 而不是 GpuTexture
    • RenderPipelines
      • GUI_OVERLAYGUI_GHOST_RECIPE_OVERLAYGUI_TEXTURED_OVERLAY 已移除
      • GUI_TEXTURED_PREMULTIPLIED_ALPHA - 一个假设纹理在合成阶段已经预乘了透明度的管线。
    • RenderStateShard
      • $Builder#add 不再接受是否应模糊着色器
      • $TextureStateShard 不再接受设置模糊模式的 TriState
    • RenderType
      • debugLine 已移除
      • guiguiOverlayguiTexturedOverlayguiOpaqueTexturedBackgroundguiNauseaOverlayguiTextHighlightguiGhostRecipeOverlayguiTextured 已移除
      • vignette 已移除
      • crosshair 已移除
      • mojangLogo 已移除
    • ScreenEffectRenderer 现在是一个实例实现,而不是仅仅一个静态方法
      • 构造函数接受当前的 Minecraft 实例和一个 MultiBufferSource
      • renderScreenEffect 现在是一个实例方法,接受实体是否在睡觉以及部分刻
      • resetItemActivationdisplayItemActivation - 处理物品自动激活时的情况(例如,图腾)。
  • net.minecraft.client.renderer.blockentity
    • *Renderer#getExtents - 将所有模型表示的变换后的向量添加到一个集合中。
    • HangingSignRenderer
      • MODEL_RENDER_SCALE 现在是公开的
      • translateBase 现在是公开的
    • SignRenderer
      • RENDER_SCALE 现在是公开的
      • applyInHandTransforms - 变换堆栈以正确表示所持告示牌的位置。
    • SkullBlockRenderer#getRenderType(SkullBlock$Type, ResolvableProfile, ResourceLocation) -> getSkullRenderTypegetPlayerSkinRenderType;不是一对一
  • net.minecraft.client.renderer.entity.ItemRenderer
    • GUI_SLOT_CENTER_XGUI_SLOT_CENTER_YITEM_DECORATION_BLIT_OFFSET 已移除
    • COMPASS_* -> SPECIAL_*
  • net.minecraft.client.renderer.item
    • ClientItem$Properties#oversizedInGui - 当为 true 时,允许物品在 GUI 中渲染到 16x16 框之外;否则,将大小裁剪到框内。
    • ItemStackRenderState
      • setAnimatedisAnimated - 返回物品是否有动画(例如,闪光)。
      • appendModelIdentityElementgetModelIdentityclearModelIdentity - 处理正在渲染的标识组件。
      • getModelBoundingBox - 计算模型的边界框。
      • setOversizedInGuiisOversizedInGui - 处理物品何时可以根据其属性在 GUI 中过大。
  • net.minecraft.client.renderer.special
    • PlayerHeadSpecialRenderer - 根据其渲染信息渲染玩家头颅。
    • SkullSpecialRenderer 现在实现 NoDataSpecialModelRenderer,不再接受模型或纹理覆盖,而是接受要使用的 RenderType
    • SpecialModelRenderer#getExtents - 将表示此渲染器使用的所有模型的变换向量添加到一个集合中。
  • net.minecraft.client.renderer.texture.TextureAtlasSprite#isAnimated - 返回精灵是否有任何动画。
  • net.minecraft.commands.arguments.ResourceOrIdArgument#dialoggetDialog$DialogArgument - 处理对话框屏幕的命令参数。
  • net.minecraft.core.registries
    • BuiltInRegistries#DIALOG_TYPEDIALOG_ACTION_TYPEINPUT_CONTROL_TYPEDIALOG_BODY_TYPE
    • Registries#DIALOG_TYPEDIALOG_ACTION_TYPEINPUT_CONTROL_TYPEDIALOG_BODY_TYPEDIALOG
  • net.minecraft.data.tags.DialogTagsProvider - 对话框的标签提供者。
  • net.minecraft.network.chat
    • ClientEvent
      • $Action#SHOW_DIALOGCUSTOM
        • valueCodec - 返回用于编码此动作的映射编解码器。
      • $Custom - 一个包含一些要发送到服务器的 nbt 有效负载的事件,目前什么都不做。
      • $ShowDialog - 一个显示指定对话框的事件。
    • CommonComponents
      • GUI_RETURN_TO_MENU - 显示“返回菜单”文本的组件。
      • disconnectButtonLabel - 根据服务器是否是本地服务器返回组件。
  • net.minecraft.network.protocol.common
    • ClientboundClearDialogPacket - 关闭当前对话框屏幕。
    • ClientboundShowDialogPacket - 打开一个新的对话框屏幕。
    • ServerboundCustomClickActionPacket - 向服务器发送一个自定义动作。
  • net.minecraft.server.dialog
    • ActionButton - 一个可以在点击时执行某些 Action 的按钮。
    • ButtonListDialog - 一个具有若干列可点击按钮的对话框模态。
    • CommonButtonData - 与对话框模态中每个按钮关联的数据。
    • CommonDialogData - 与每个对话框模态关联的数据。
    • ConfirmationDialog - 一个可以选择是或否的对话框模态。
    • Dialog - 定义某个对话框模态的基础接口。
    • DialogAction - 通常在点击某个动作按钮后执行的动作。
    • DialogListDialog - 一个指向其他对话框的按钮的可滚动列表。
    • Dialogs - 一个注册 Dialog 的数据包引导程序。
    • DialogTypes - 用于编码某个对话框模型的映射编解码器注册表。
    • Input - 一个将某个键映射到 InputControl 的处理程序。
    • MultiActionDialog - 一个按列排列的动作的可滚动列表。
    • NoticeDialog - 一个在页脚中只有一个动作的简单屏幕。
    • ServerLinksDialog - 一个从服务器接收的链接的可滚动列表,按列排列。
    • SimpleDialog - 一个定义可以采取的主要动作的对话框。
  • net.minecraft.server.dialog.action
    • Action - 对某些输入执行的通用操作,通常是按钮点击。
    • ActionTypes - 用于编码某个动作的映射编解码器注册表。
    • CustomTemplate - 构建一个命令并请求服务器运行它。
    • CustomAll - 从所有输入构建一个自定义服务器点击动作,并请求服务器运行它。
    • ParsedTemplate - 一个编码某些字符串的模板,类似于函数宏的工作方式。
    • StaticAction - 一个在激活时触发 ClickEvent 的动作。
  • net.minecraft.server.dialog.body
    • DialogBody - 描述标题和动作/输入之间内容的主体元素。
    • DialogBodyTypes - 用于编码某个主体的映射编解码器注册表。
    • ItemBody - 一个带有可选描述的物品。
    • PlainMessage - 一个多行标签。
  • net.minecraft.server.dialog.input
    • BooleanInput - 一个带有标签的普通复选框。
    • InputControl - 一个接受用户输入的控制机制。
    • InputControlTypes - 用于编码某个输入控件的映射编解码器注册表。
    • NumberRangeInput - 一个用于从某个范围内选择数值的滑块。
    • SingleOptionInput - 一个在一组选项之间循环的按钮。
    • TextInput - 简单的文本输入。
  • net.minecraft.world.entity.player.Player#openDialog - 打开指定的对话框屏幕。

路径点

路径点只是一种跟踪游戏中某些对象位置的方法。底层系统由 WaypointManager 处理,负责保存它正在跟踪的路径点,同时允许根据需要更新和移除。服务器通过 ServerWaypointManager(通过 ServerLevel#getWaypointManager 获得)处理路径点,它持有一个到发射器的活动连接以接收实时更新。客户端通过 ClientWaypointManager(通过 ClientPacketListener#getWaypointManager 获得)接收这些路径点,它仅保存某些标识符以及精确位置、如果位置不在视野距离内的区块,或者如果距离大于存储的 Waypoint$Fade#farDist(默认超过 332 个方块)则保存一个角度。

实体默认跟踪路径点。

样式和图标

每个路径点都由某种图标表示,由其 WaypointStyle 和图标的颜色定义。WaypointStyle 类似于客户端物品或装备模型,它具有一个由 WaypointStyleAsset 指向的键,位于 assets/<modid>/waypoint_style/<path>.json 中。这包含一个位于 assets/<modid>/textures/gui/sprites/hud/locator_bar_dot/<path>.png 中的精灵列表,根据与跟踪器的距离选择。精灵在由近和远距离指定的范围内变化。

// 对于某个样式 examplemod:example_style
// 它将在 `assets/examplemod/waypoint_style/example_style.json` 中找到
{
    // 表示任何更近的值将在渲染条时使用第一个精灵
    // 未指定时默认为 128
    "near_distance": 100,
    // 表示任何更远的值将在渲染条时使用最后一个精灵
    // 未指定时默认为 332
    // 必须大于近距离
    "far_distance": 400,
    // 一个相对于 `assets/<modid>/textures/gui/sprites/hud/locator_bar_dot/<path>.png` 的非空纹理列表
    // 这是用于在两个距离之间进行插值的内容
    "sprites": [
        // 指向 `assets/examplemod/textures/gui/sprites/hud/locator_bar_dot/example_style_0.png`
        "examplemod:example_style_0",
        "examplemod:example_style_1",
        "examplemod:example_style_2"
    ]
}

然后可以使用其构造函数构造图标,并通过服务器上的 WaypointTransmitter#waypointIcon 或客户端上的 TrackedWaypoint#icon 引用。

// 我们将假设此构造函数被公开以用于更动态的用法
// 目前,它只能通过其 `CompoundTag` 在 `LivingEntity` 上通过 `locator_bar_icon` 设置
public static Waypoint.Icon EXAMPLE_ICON = new Waypoint.Icon(
    // 路径点样式的注册表键
    // 指向 `assets/examplemod/waypoint_style/example_style.json`
    ResourceKey.create(WaypointStyleAssets.ROOT_ID, ResourceLocation.fromNamespaceAndPath("examplemod", "example_style")),
    // 路径点的颜色
    // 当不存在时,使用路径点标识符的哈希码
    Optional.of(0xFFFFFF)
);

连接

当跟踪路径点时,它们通过 WaypointTransmitter$Connection 进行管理。一个连接负责将信息同步到客户端,无论是连接、断开连接还是更新。

public class ExampleBlockConnection implements WaypointTransmitter.Connection {

    private final BlockState state;
    private final BlockPos pos;
    private final Waypoint.Icon icon;
    private final ServerPlayer receiver;

    public ExampleBlockConnection(BlockState state, BlockPos pos, Waypoint.Icon icon, ServerPlayer receiver) {
        this.state = state;
        this.pos = pos;
        this.icon = icon;
        this.recevier = receiver;
    }

    public static boolean doesSourceIgnoreReceiver(BlockPos pos, ServerPlayer player) {
        double receiveRange = player.getAttributeValue(Attributes.WAYPOINT_RECEIVE_RANGE);
        return pos.distSqr(player.blockPosition()) >= receiveRange * receiveRange;
    }

    @Override
    public boolean isBroken() {
        // 当为 true 时,它将尝试重新建立到此发射器的连接
        // 仅在更新位置时调用
        return ExampleBlockConnection.doesSourceIgnoreReceiver(this.pos, this.receiver);
    }

    @Override
    public void connect() {
        // 这会将跟踪数据包发送到客户端
        this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointPosition(this.state.toString() + ": " + this.pos.toString(), this.icon, this.pos));
    }

    @Override
    public void disconnect() {
        // 这会将移除数据包发送到客户端
        this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.state.toString() + ": " + this.pos.toString()));
    }

    @Override
    public void update() {
        // 这会在客户端上更新跟踪值,假设连接没有中断
        // 在我们的例子中,我们可以假设这永远不会改变,因为方块的位置应该是一致的
    }
}

发射器

一个 WaypointTransmitter 负责在其和服务器之间建立连接。为了让您的对象传输位置,它必须实现 WaypointTransmitter 及其三个方法。waypointIcon 仅返回要显示的图标。isTransmittingWaypoint 将确定是否可以从该对象传输路径点。makeWaypointConnectionWith 实际处理用于跟踪连接的位置或角度的连接的构造。

public class ExampleWaypointBlock extends BlockEntity implements WaypointTransmitter {

    // ...

    @Override
    public boolean isTransmittingWaypoint() {
        // 如果不应该建立连接,则应返回 false
        return true;
    }

    @Override
    public Optional<WaypointTransmitter.Connection> makeWaypointConnectionWith(ServerPlayer player) {
        // 如果没有被忽略,则创建一个连接
        return ExampleBlockConnection.doesSourceIgnoreReceiver(this.getBlockPos(), player)
            ? Optional.empty()
            : Optional.of(new ExampleBlockConnection(this.getBlockState(), this.getBlockPos(), this.waypointIcon(), player));
    }

    @Override
    public Waypoint.Icon waypointIcon() {
        return EXAMPLE_ICON;
    }
}

然后,您需要做的就是根据需要跟踪、更新或取消跟踪发射器。这可以使用 ServerWaypointManager 提供的方法来完成:

// 我们将假设我们可以访问:
// - ServerLevel serverLevel
// - ExampleWaypointBlock be

// 跟踪路径点,例如在某个初始化时
serverLevel.getWaypointManager().trackWaypoint(be);

// 如果位置改变,更新路径点
serverLevel.getWaypointManager().updateWaypoint(be);

// 一旦路径点不再存在,将其移除
serverLevel.getWaypointManager().untrackWaypoint(be);
  • net.minecraft.client
    • Camera 现在实现 TrackedWaypoint$Camera
    • Minecraft#getWaypointStyles - 返回一个键到路径点样式的管理器。
  • net.minecraft.client.data.models.WaypointStyleProvider - 一个生成路径点样式的数据提供者。
  • net.minecraft.client.multiplayer.ClientPacketListener#getWaypointManager - 获取用于跟踪路径点的客户端管理器。
  • net.minecraft.client.renderer.GameRenderer 现在实现 TrackedWaypoint$Projector
  • net.minecraft.client.resources
    • WaypointStyle - 定义用于渲染路径点的样式。
    • WaypointStyleManager - 将某个键映射到路径点样式的管理器。
  • net.minecraft.client.waypoints.ClientWaypointManager - 用于跟踪路径点的客户端管理器。
  • net.minecraft.commands.arguments.WaypointArgument - 一个静态方法持有者,用于从实体获取某个路径点发射器。
  • net.minecraft.network.protocol.game
    • ClientboundTrackedWaypointPacket - 一个向客户端发送某个路径点操作的数据包。
    • ClientGamePacketListener#handleWaypoint - 在客户端上处理路径点数据包。
  • net.minecraft.server.ServerScoreboard$Method 枚举已移除
  • net.minecraft.server.level.ServerLevel#getWaypointManager - 获取用于跟踪路径点的服务器管理器。
  • net.minecraft.server.level.ServerPlayer#isReceivingWaypoints - 玩家是否从其他位置或实体接收路径点。
  • net.minecraft.server.waypoints.ServerWaypointManager - 用于跟踪路径点(例如,玩家和发射器)的服务器端管理器。
  • net.minecraft.world.entity
    • Entity#getRequiresPrecisePositionsetRequiresPrecisePosition - 处理何时需要更精确的位置进行跟踪。
    • LivingEntity 现在实现 WaypointTransmitter
  • net.minecraft.world.waypoints
    • TrackedWaypoint - 一个由某个 UUID 或字符串标识、通过 Waypoint$Icon 显示并由 $Type 指定的路径点。
    • TrackedWaypointManager - 一个用于 TrackedWaypoint 的路径点管理器。
    • Waypoint - 一个表示某个位置位置的接口。它不保存任何信息,通常在 TrackedWaypoint 的上下文中使用。
    • WaypointManager - 一个跟踪和更新路径点的接口。
    • WaypointStyleAsset - 一个表示样式资源的类。
    • WaypointStyleAssets - 一个定义所有原版样式资源的类。
    • WaypointTransmitter - 一个传输某个可以连接和跟踪的位置的对象。

Blaze3d 变更

就像上一次更新一样,Blaze3d 有新的重新设计,改变了渲染的处理方式。

缓冲区切片

渲染系统中最重要的是使用 GpuBufferSlice。顾名思义,它只是获取 GpuBuffer 的某个切片,使用 offset 指示起始索引,length 指示其大小。在处理任何与渲染相关的事情时,即使传递给着色器,您几乎总是会处理 GpuBufferSlice。可以这样理解:缓冲区只是某个对象的任意列表,而切片代表一个特定的对象。

要创建一个切片,只需调用 GpuBuffer#slice,可选择提供起始索引和长度。在大多数情况下,您不会直接调用此方法,而是处理为您调用它的其他方法。请注意,由于您通常将数据写入这些切片,它们应该在创建 try-with-resources RenderPass 之前构建。

统一变量重做

统一变量系统已被完全改造,以至于除非您熟悉特定功能,否则它可能看起来完全陌生。简而言之,统一变量现在存储为接口对象、纹素缓冲区或采样器。这些由 GpuBufferGpuBufferSlice 填充。

统一变量类型

一个统一变量目前表示为两种 UniformType 之一:UNIFORM_BUFFER/接口块,或 TEXEL_BUFFER。在设置管道并调用 withUniform 时,您必须使用上述类型之一指定您的统一变量。如果您选择使用纹素缓冲区,还必须指定纹理数据的格式。采样器没有变化。

public static final RenderPipeline EXAMPLE_PIPELINE = RenderPipeline.builder(...)
    // 使用名为 'ExampleUniform' 的统一接口块
    .withUniform("ExampleUniform", UniformType.UNIFORM_BUFFER)
    // 使用名为 'ExampleTexel' 的缓冲区,将纹理数据存储为 8 位 R 值
    .withUniform("ExampleTexel", UniformType.TEXEL_BUFFER, TextureFormat.RED8I)
    // 执行其他设置
    .build();

接口块

一个 UNIFORM_BUFFER 存储为一个 std140 接口块。在 GLSL 中,它表示如下:

// 在 assets/examplemod/shaders/core/example_shader.json

// ExampleUniform 是块的名称
layout(std140) uniform ExampleUniform {
    // 块内的数据
    // 后处理效果只能使用 int, float, vec2, vec3, ivec3, vec4, 或 mat4
    vec4 Param1;
    float Param2;
};

可以在主块内自由使用这些值,如下所示:

// 在 assets/examplemod/shaders/core/example_shader.json

out vec4 fragColor;

void main() {
    fragColor = Param1;
}

统一块可以位于与主函数相同的文件中,或者如果将被重用,可以作为 moj_import,其中统一文件位于 assets/<modid>/shaders/include/<path> 内。请注意,在资源包加载之前使用的任何着色器都不能使用 moj_import

后处理效果在 uniform 输入中定义其接口块:

// 在 assets/examplemod/post_effect/example_post_effect.json
// 在 'passes' 对象内部
{
    "vertex_shader": "...",
    // ...
    "uniforms": {
        // 接口块的名称
        "ExampleUniform": [
            // 统一块内的一个参数
            // 有关编解码器格式,请参阅 `UniformValue`
            {
                // 参数的名称
                "name": "Param1",
                // 参数类型,之一:
                // - int
                // - ivec3
                // - float
                // - vec2
                // - vec3
                // - vec4
                // - matrix4x4 (mat4)
                "type": "vec4",
                // 存储在统一变量中的值
                // 不再支持来自代码库的动态值
                "value": [ 0.0, 0.0, 0.0, 0.0 ]
            },
            {
                "name": "Param2",
                "type": "float",
                "value": 0
            }
        ]
    }
}

纹素缓冲区

纹素缓冲区通常表示为 isamplerBuffer 以供查询,通常使用 texelFetch

// 在 assets/examplemod/shaders/core/example_shader.json

uniform isamplerBuffer ExampleTexel;

void main() {
    // 阅读文档以了解 texel fetch 的工作原理
    texelFetch(ExampleTexel, gl_InstanceID);
}

编写自定义统一变量

只有当您负责创建 RenderPass 时,才能编写自定义统一变量。与之前一样,您在打开 RenderPass 之前创建并缓存对象,然后通过调用 RenderPass#withUniform 设置统一变量。唯一的区别是,现在您必须提供一个 GpuBufferGpuBufferSlice,其中写入了统一数据,而不是提供任意对象。对于纹素缓冲区,这通常是一些所需纹理格式的编码数据(例如网格)。对于接口块,最简单的方法是使用 Std140Builder 用正确的值填充缓冲区。

写入 GpuBufferGpuBufferSlice 有很多不同的方法,例如使用新创建的 MappableRingBuffer。由您决定哪种方法最适合您的场景。以下只是众多解决方案中的一种。

// 用于 'ExampleUniform' 的缓冲区
// 接受缓冲区的名称、其用法和大小
private final MappableRingBuffer ubo = new MappableRingBuffer(
    // 缓冲区名称
    () -> "Example UBO",
    // 缓冲区用法
    // 我们设置 128,因为它用于统一变量,并且设置 2 因为我们正在写入它
    // 其他位可以在 `GpuBuffer` 中作为常量找到
    GpuBuffer.USAGE_UNIFORM | GpuBuffer.USAGE_MAP_WRITE,
    // 缓冲区的大小
    // 最简单的方法是使用 Std140SizeCalculator 正确计算
    new Std140SizeCalculator()
        // Param1
        .putVec4()
        // Param2
        .putFloat()
        .get()
);

// 用于 'ExampleTexel' 的缓冲区
private final MappableRingBuffer utb = new MappableRingBuffer(
    // 缓冲区名称
    () -> "Example UTB",
    // 我们设置 256,因为它用于纹素缓冲区,并且设置 2 因为我们正在写入它
    GpuBuffer.USAGE_UNIFORM_TEXEL_BUFFER | GpuBuffer.USAGE_MAP_WRITE,
    // 缓冲区的大小
    // 对您来说可能会更大
    3
);

// 在某个渲染方法中

// 根据需要填充缓冲区

// 由于我们使用环形缓冲区,这只是使用列表中的下一个可用缓冲区
this.ubo.rotate();
// 将数据写入缓冲区
try (GpuBuffer.MappedView view = RenderSystem.getDevice().createCommandEncoder().mapBuffer(this.ubo.currentBuffer(), false, true)) {
    Std140Builder.intoBuffer(view.data())
        .putVec4(0f, 0f, 0f, 0f)
        .putFloat(0f);
}

// 类似的事情
this.utb.rotate();
try (GpuBuffer.MappedView view = RenderSystem.getDevice().createCommandEncoder().mapBuffer(this.utb.currentBuffer(), false, true)) {
    view.data()
        .put((byte) 0)
        .put((byte) 0)
        .put((byte) 0);
}

// 创建渲染通道并传入缓冲区作为统一变量的一部分
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(...)) {
    // ..
    pass.setUniform("ExampleUniform", this.ubo.currentBuffer());
    pass.setUniform("ExampleTexel", this.utb.currentBuffer());
    // ...
}

雾环境

雾系统已被重做为环境/渲染状态式的处理程序。每个环境主要负责设置雾数据和颜色。为各个 FogType 和特殊状态效果提供了一些额外的处理。

所有环境都通过 FogEnvironment 处理。通过 setupFog 方法设置环境,该方法负责将传入的 FogData 更改为与该环境关联的值。如果雾对其周围环境着色,则 providesColor 应返回 true,并在 getBaseColor 中应用基本颜色色调。同样,如果雾使其周围环境变暗,则 modifiesDarkness 应返回 true,并通过 getModifiedDarkness 返回修改后的暗度。要确定是否应应用环境,会检查 isApplicable。如果不可用,则调用 onNotApplicable

所有环境都注册到 FogRenderer#FOG_ENVIRONMENTS;然而,使用哪个环境基于 isApplicable 和列表顺序。对于颜色和暗度,选择的雾环境是列表中最后一个 provides* 方法之一返回 true 的环境。对于实际的雾设置,选择的雾环境是列表中的第一个。

渲染通道剪裁现在仅限 OpenGL

剪裁状态已从通用管线代码中移除,现在只能通过 OpenGL 实现访问。通用区域处理已委托给 CommandEncoder#clearColorAndDepthTextures。请注意,这不会影响处理面向 blit 的剪裁的现有 ScreenRectangle 系统。

  • com.mojang.blaze3d.buffers
    • BufferType 枚举已移除
    • BufferUsage 枚举已移除
    • GpuBuffer 现在接受两个整数表示大小和用法,不再指定类型
      • type 已移除
      • usage 现在返回一个 int
      • slice - 返回一个表示某个缓冲区切片的记录。实际缓冲区不以任何方式修改。
      • $ReadView -> $MappedView
    • GpuBufferSlice - 一个记录,通过持有对整个缓冲区的引用、起点的偏移索引和切片的长度来表示某个缓冲区的切片。
    • GpuFence 现在是一个接口,其 OpenGL 实现已移至 blaze3d.opengl.GlFence
    • Std140Builder - 一个用于以 std140 格式布局的接口块的缓冲区插入器。用于着色器中的统一块。
    • Std140SizeCalculator - 一个用于跟踪某个接口块大小的对象。
  • com.mojang.blaze3d.opengl
    • AbstractUniform 已移除,被 Std140* 类取代
    • BufferStorage - 一个根据其类型创建缓冲区的类。其实现定义了其一般用途。
    • DirectStateAccess
      • createBuffer - 创建一个缓冲区。
      • bufferData - 初始化缓冲区的数据存储。
      • bufferSubData - 更新缓冲区数据存储的子集。
      • bufferStorage - 创建缓冲区的数据存储。
      • mapBufferRange - 映射缓冲区数据存储的一部分。
      • unmapBuffer - 释放缓冲区的映射并使指向其数据存储的指针无效。
    • GlBuffer 现在接受一个 DirectStateAccess、两个整数和一个 ByteBuffer,而不是 GlDebugLabel 及其 Buffer* 枚举
      • initialized 已移除
      • persistentBuffer - 持有对某个缓冲区不可变部分的引用。
      • $ReadView -> $GlMappedView
    • GlCommandEncoder
      • executeDrawMultiple 现在接受一个字符串集合,定义所需统一变量的列表,以及一个表示绘制调用对象的泛型
      • executeDraw 现在接受两个 int,要渲染的指定索引范围的实例数和基础顶点
    • GlConst#toGl 用于 BufferTypeBufferUsage -> bufferUsageToGlFlagbufferUsageToGlEnum
    • GlDebugLabel#pushDebugGrouppopDebugGroup - 用于对类似调用进行分组的分析器命令。
    • GlDevice
      • USE_GL_ARB_buffer_storage - 设置 GL_ARB_buffer_storage 的扩展标志。
      • getBufferStorage - 返回负责创建缓冲区的存储。
    • GlProgram
      • Uniform 字段已移除
      • safeGetUniformsetDefaultUniforms 已移除
      • bindSampler 已移除
      • getSamplerLocationsgetSamplersgetUniforms -> getUniforms,返回名称到其 Uniform 对象的映射
    • GlRenderPass
      • uniforms 现在是一个 HashMap<String, GpuBufferSlice>
      • dirtSamplers 已移除
      • samplers 映射现在持有 GpuTextureView
      • pushedDebugGroups - 返回推送到堆栈上的组数。关闭渲染通道时不得有任何调试组打开。
      • isScissorEnabled - 返回是否启用剪裁状态,该状态会裁剪渲染到屏幕的区域。
      • getScissorXgetScissorYgetScissorWidthgetScissorHeight - 返回表示剪裁矩形的值。
    • GlTexture 现在接受一个额外的整数用于用法和深度/层数
      • flushModeChanges 现在接受一个表示纹理目标的 int
      • addViewsremoveViews - 管理针对某些 mip 级别的纹理视图。
    • GlTextureView - 针对某些 mip 级别的纹理的视图实现。
    • Uniform 现在是一个密封接口,实现为缓冲区对象、纹素缓冲区或采样器
  • com.mojang.blaze3d.pipeline
    • BlendFunction#PANORAMA 已移除
    • CompiledRenderPipeline#containsUniform 已移除
    • RenderPipeline
      • $Builder#withUniform 现在有一个可以接受 TextureFormat 的重载
      • $UniformDescription 现在接受一个可为 null 的 TextureFormat
    • RenderTarget
      • colorTextureViewdepthTextureViewgetColorTextureViewgetDepthTextureView - 当前颜色和深度纹理的视图。
      • blitAndBlendToTexture 现在接受 GpuTextureView 而不是 GpuTexture
  • com.mojang.blaze3d.platform.Lightning 现在是 AutoCloseable
    • setup* -> setupFor,一个接受 $Entry 的实例方法
    • updateLevel - 更新光照缓冲区,接受是否使用下界漫射光照。
  • com.mojang.blaze3d.shaders
    • FogShape -> net.minecraft.client.renderer.fog.FogData,不是一对一
    • UniformType 现在只包含两种类型:UNIFORM_BUFFERTEXEL_BUFFER,不再接受计数
  • com.mojang.blaze3d.systems
    • CommandEncoder
      • clearColorAndDepthTextures 现在有一个接受四个 int 的重载,表示要清除纹理信息的区域
      • writeToBuffermapBuffer(GpuBuffer, int, int) 现在接受 GpuBufferSlice 而不是 GpuBuffer
      • createFence - 创建一个新的同步围栏。
      • createRenderPass 现在接受一个 Supplier<String>,用于确定用作调试组的通道名称,以及 GpuTextureView 而不是 GpuTexture
      • writeToTexture 现在接受一个额外的 int,表示要写入的深度或层
      • presentTexture 现在接受 GpuTextureView 而不是 GpuTexture
    • GpuDevice
      • createBuffer 不再接受 BufferUsageBufferTypeint 取代
      • getUniformOffsetAlignment - 返回统一缓冲区偏移对齐。
      • createTexture 现在接受额外的 int 用于用法和深度/层数,请参阅 GpuTexture 常量
      • createTextureView - 为某个 mip 级别范围创建纹理视图。
    • RenderPass
      • enableScissor 已移除
      • bindSampler 现在可以接受一个可为 null 的 GpuTextureView
      • setUniform 现在可以接受 GpuBufferGpuBufferSlice 而不是原始输入
      • drawIndexed 现在接受以下 int:基础顶点、起始索引、元素数和原始计数
      • drawMultipleIndexed 现在接受一个字符串集合,定义所需统一变量的列表,以及一个表示绘制调用对象的泛型
      • pushDebugGrouppopDebugGroup - 用于对类似调用进行分组的分析器命令。
      • $UniformUploader#upload 现在接受 GpuBufferSlice 而不是 float 数组
      • $Draw 现在有一个泛型,用于将任何统一变量上传到缓冲区
    • RenderSystem
      • SCISSOR_STATE -> scissorStateForRenderTypeDraws,现在是私有的
        • 可通过 getScissorStateForRenderTypeDraws 访问
      • enableScissordisableScissor -> enableScissorForRenderTypeDrawsdisableScissorForRenderTypeDraws,不是一对一
      • PROJECTION_MATRIX_UBO_SIZE - 返回投影矩阵统一变量的大小
      • setShaderFoggetShaderFog 现在处理 GpuBufferSlice
      • setShaderGlintAlphagetShaderGlintAlpha 已移除
      • setShaderLightsgetShaderLights 现在处理 GpuBufferSlice
      • setShaderColorgetShaderColor
      • setup*Lighting 方法已移除
      • setProjectionMatrixgetProjectionMatrix(现在为 getProjectionMatrixBuffer)现在处理 GpuBufferSlice
      • setShaderGameTimegetShaderGameTime -> setGlobalSettingsUniformgetGlobalSettingsUniform;不是一对一
      • getDynamicUniforms - 返回要为着色器写入的统一变量列表。
      • bindDefaultUniforms - 绑定要在 RenderPass 内使用的默认统一变量
      • outputColorTextureOverrideoutputDepthTextureOverride 现在是 GpuTextureView
      • setupOverlayColorsetShaderTexturegetShaderTexture 现在操作 GpuTextureView 而不是 GpuTexture
  • com.mojang.blaze3d.textures
    • GpuTexture 现在接受一个表示用法标志和深度/层数的 int
      • usage - 定义纹理如何使用的标志。
      • depthOrLayersgetDepthOrLayers - 定义给定纹理可用的层数或深度。这是作为可用纹理编码的通用计数。目前仅支持立方体贴图(意味着层数必须是 6 的倍数)。
    • GpuTextureView - 针对某个 mip 级别范围的纹理视图。
    • TextureFormat#RED8I - 处理红色通道的 8 位有符号整数。
  • com.mojang.blaze3d.vertex
    • ByteBufferBuilder 现在接受一个 long 作为最大容量
      • exactlySized - 返回一个达到其最大容量的缓冲区。应优先于公共构造函数调用此方法。
    • DefaultVertexFormat#EMPTY - 一个没有元素的顶点格式。
  • net.minecraft.client.renderer
    • CachedOrthoProjectionMatrixBuffer - 一个缓存正交投影矩阵的对象,如果屏幕宽度或高度改变,则重新构建。
    • CachedPerspectiveProjectionMatrixBuffer - 一个缓存透视投影矩阵的对象,如果宽度、高度或视野改变,则重新构建。
    • CloudRenderer
      • FLAG_INSIDE_FACEFLAG_USE_TOP_COLOR 现在是私有的
      • RADIUS_BLOCKS 已移除
      • endFrame - 通过构造围栏结束当前正在渲染的帧。
    • CubeMap 现在是 AutoCloseable
      • render 不再接受部分刻的浮点数。
    • DynamicUniforms - 一个将统一接口块写入缓冲区以供着色器使用的类。
    • DynamicUniformStorage - 一个将统一变量保存在可映射环形缓冲区切片中的类。
    • FogParameters 记录已移除,现在存储在一个通用的 GpuBufferSlice
    • FogRenderer 现在实现 AutoCloseable -> .fog.FogRenderer
      • endFrame - 通过构造围栏结束当前正在渲染的帧。
      • getBuffer - 获取持有当前雾模式统一变量的缓冲区切片。
      • setupFog 不再接受 FogMode,不返回任何内容
      • $FogData#mode 已移除,被 skyEndcloudEnd 取代
      • $FogMode 枚举已被 NONEWORLD 取代,不是一对一
    • GameRenderer
      • getGlobalSettingsUniform - 返回游戏设置的统一变量。
      • getLighting - 获取光照渲染器。
      • setLevel - 设置渲染器正在渲染的当前等级。
    • GlobalSettingsUniform - 一个用于处理持有当前游戏设置的统一变量的对象。
    • LevelRenderer
      • endFrame - 通过构造围栏结束当前正在渲染的帧。
      • renderLevel 现在接受一个 GpuBufferSlice、雾向量以及当前位置是否有雾,而不是 GameRenderer
    • MappableRingBuffer - 一个包含三个缓冲区的对象,根据需要写入,然后在结束时旋转到下一个要使用的缓冲区。这些使用围栏进行同步。
    • PanoramaRenderer#render 现在接受一个布尔值,表示是否改变旋转,而不是两个浮点数。
    • PerspectiveProjectionMatrixBuffer - 一个持有投影矩阵统一变量的对象。
    • PostChain
      • load 现在接受 CachedOrthoProjectionMatrixBuffer
      • addToFrame 不再接受 Consumer<RenderPass>
      • process 不再接受 Consumer<RenderPass>
    • PostChainConfig
      • $FixedSizedTarget 记录已移除
      • $FullScreenTarget 记录已移除
      • $InternalTarget 现在是一个记录,可以接受可选的宽度、高度、目标是否持久以及要使用的清除颜色
      • $Pass#uniforms 现在是一个 Map<String, List<UniformValue>>
      • $Uniform 记录已移除
    • PostPass 现在是 AutoCloseable,接受一个 Map<String, List<UniformValue>> 作为统一变量,以及一个 PostPass$Input 列表
      • addToFrame 不再接受 Consumer<RenderPass>Matrix4f 作为 GpuBufferSlice 传入
      • $Input
        • bindTo 已移除
        • texture - 根据资源映射为输入构造一个 GpuTexture
        • samplerName - 返回采样器的名称。
    • SkyRenderer#renderSunMoonAndStars 不再接受 FogParameters
    • UniformValue - 一个表示存储在接口块内的统一变量的接口。
  • net.minecraft.client.renderer.chunk.SectionRendererDispatcher$RenderSection#setDynamicTransformIndexgetDynamicTransformIndex - 处理用于查询给定部分的正确动态变换的索引。
  • net.minecraft.client.renderer.fog.environment
    • AirBasedFogEnvironment - 一个其颜色源自生物群系空气的环境
    • AtmosphericFogEnvironment - 如果没有其他特殊情况匹配,则为默认雾环境。
    • BlindessFogEnvironment - 如果实体有失明效果,则激活的环境。
    • DarknessFogEnvironment - 如果实体有黑暗效果,则激活的环境。
    • DimensionOrBossFogEnvrionment - 根据是否有任何 Boss 或维度特殊效果而激活的环境。
    • FogEnvironment - 一个抽象类,确定雾在给定位置应如何为实体渲染。
    • LavaFogEnvironment - 如果实体在熔岩中,则激活的环境。
    • MobEffectFogEnvironment - 根据实体是否有给定的状态效果而激活的环境。
    • PowderedSnowFogEnvironment - 如果实体在细雪中,则激活的环境。
    • WaterFogEnvironment - 如果实体在水中,则激活的环境。
  • net.minecraft.client.renderer.texture
    • AbstractTexture
      • setUseMipmaps - 设置纹理是否应使用 mipmapping。
      • textureViewgetTextureView - 表示当前的纹理视图。
    • CubeMapTexture - 一个兼容立方体贴图的纹理,纹理预期具有后缀 _0_5
    • ReloadableTexture#doLoad 现在是 protected
  • net.minecraft.world.level.material.FogType
    • DIMENSION_OR_BOSS - 用于维度特殊效果或 Boss 的雾。
    • ATMOSPHERIC - 默认雾类型。

TagAppender 重写

TagAppender 已被重写,改变了 TagsProvider 的基本实现。

默认情况下,TagsProvider 不再提供任何用于向 TagBuilder 添加内容的有用方法。您最多可以使用 TagsProvider#getOrCreateRawBuilder 构造构建器,并使用可用的 add* 方法之一通过其 ResourceLocation 添加元素或标签。

// 我们将假设存在某个 TagKey<Item> EXAMPLE_TAG
public class ExampleTagsProvider extends TagsProvider<Item> {

    public ExampleTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries, CompletableFuture<TagsProvider.TagLookup<Item>> parentProvider) {
        super(
            // 资源包的输出位置
            output,
            // 要为其生成标签的注册表键
            Registries.ITEM,
            // 注册表的注册表
            registries,
            // 可选:要使用其生成标签的父提供者
            // 通常从 TagsProvider#contentsGetter 获得
            parentProvider
        );
    }

    @Override
    protected void addTags(HolderLookup.Provider registries) {
        // 在此处添加标签
        TagBuilder builder = this.getOrCreateRawBuilder(EXAMPLE_TAG);
        builder
            // 添加单个元素
            .addElement(ResourceLocation.fromNamespaceAndPath("minecraft", "apple"))
            // 将标签添加到构建器
            .addTag(ItemTags.WOOL.location());
    }
}

但是,如果我们想通过其 ResourceKey 引用标签呢?或者注册表对象?这就是重写的 TagAppender 的作用。TagAppender 是一个具有两个泛型的接口,E 表示要添加的条目的类型,T 表示标签内对象的类型。一个 TagAppender 有五个常见方法:三个添加条目(addaddAlladdOptional),两个添加标签(addTagaddOptionalTag)。可以通过 forBuilder 创建 TagAppender,它接受条目的 ResourceKey

KeyTagProvider 通过添加一个 tag 方法为您提供此功能,该方法从 TagKey 创建追加器。通常,数据包注册表对象使用此提供者生成其标签:

// 我们将假设存在某个 TagKey<Item> EXAMPLE_TAG
public class ExampleTagsProvider extends KeyTagProvider<Item> {

    public ExampleTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
        super(
            // 资源包的输出位置
            output,
            // 要为其生成标签的注册表键
            Registries.ITEM,
            // 注册表的注册表
            registries
        );
    }

    @Override
    protected void addTags(HolderLookup.Provider registries) {
        // 在此处添加标签
        TagAppender<ResourceKey<Item>, Item> builder = this.tag(EXAMPLE_TAG);
        builder
            // 添加单个元素
            .add(ResourceKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath("minecraft", "apple")))
            // 将标签添加到构建器
            .addTag(ItemTags.WOOL);
    }
}

TagAppender 也可以使用 map 方法来更改其条目类型。这接受一个将新条目类型映射到原始条目类型的函数。IntrinsicHolderTagsProvider 通过一个 tag 方法为您提供此功能,该方法从 TagKey 创建追加器,并使用键提取器进行映射。通常,内置注册表对象使用此提供者生成其标签:

// 我们将假设存在某个 TagKey<Item> EXAMPLE_TAG
public class ExampleTagsProvider extends IntrinsicHolderTagsProvider<Item> {

    public ExampleTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
        super(
            // 资源包的输出位置
            output,
            // 要为其生成标签的注册表键
            Registries.ITEM,
            // 注册表的注册表
            registries,
            // 将注册表对象映射到其资源键
            item -> item.builtInRegistryHolder().key()
        );
    }

    @Override
    protected void addTags(HolderLookup.Provider registries) {
        // 在此处添加标签
        TagAppender<Item, Item> builder = this.tag(EXAMPLE_TAG);
        builder
            // 添加单个元素
            .add(Items.APPLE)
            // 将标签添加到构建器
            .addTag(ItemTags.WOOL);
    }
}

复制标签:方块和物品

复制标签不再以传统意义存在,即遍历现有标签的元素。相反,实现已被缩小到一个通用的 BlockItemTagsProvider。此方法通过同时接受方块和物品标签,并在 Vanilla*TagsProvider 中适当地转换它们,来提供 TagAppender<Block, Block>。因此,与其说是复制,不如说是将方块映射到其关联的物品。

一个缺点是,在其他标签中使用的标签(调用 addTag)必须具有相同的名称。例如,添加 BlockTags#LOGS 之所以有效,是因为存在一个 minecraft:logs 同时用于方块和物品标签。同时,添加 BlockTags#CEILING_HANGING_SIGNS 会失败,因为关联的物品标签是 minecraft:hanging_signs 而不是 minecraft:ceiling_hanging_signs

// 我们将假设存在某个 TagKey<Block> BLOCK_EXAMPLE_TAG
// 我们将假设存在某个 TagKey<Item> ITEM_EXAMPLE_TAG
public class ExampleBlockItemTagsProvider extends BlockItemTagsProvider {

    @Override
    public void run() {
        // 在此处添加方块物品标签
        // 将根据提供者向方块或物品标签添加条目
        TagAppender<Block, Block> builder = this.tag(BLOCK_EXAMPLE_TAG, ITEM_EXAMPLE_TAG);
        builder
            // 添加单个元素
            .add(Blocks.TERRACOTTA)
            // 将标签添加到构建器
            // 在方块和物品标签中都存在 `minecraft:logs`
            .addTag(BlockTags.LOGS);
    }
}

// 对于某个 IntrinsicHolderTagsProvider<Item> 或 IntrinsicHolderTagsProvider<Block>
@Override
protected void addTags(HolderLookup.Provider registries) {
    // 在此处添加标签
    new ExampleBlockItemTagsProvider() {
        // 或 <Item, Item> 取决于情况
        protected TagAppender<Block, Block> tag(TagKey<Block> blockTag, TagKey<Item> itemTag) {
            // 返回一个 TagAppender
            // 有关物品示例,请参阅 VanillaItemTagsProvider$BlockToItemConverter
            // 有关方块示例,请参阅 VanillaBlockTagsProvider
        }
    }.run();
}
  • net.minecraft.data.tags
    • BlockItemTagsProvider - 一个为方块物品生成标签的提供者,使用方块和物品标签等效项作为起点。
    • IntrinsicHolderTagsProvider
      • tag 现在返回原始的 TagAppender
      • $IntrinsicTagAppender 类已移除
    • ItemTagsProvider 类已移除
    • KeyTagProvider - 一个通过其 ResourceKey 追加元素的提供者。
    • TagsProvider
      • tag 已移除
      • $TagAppender -> TagAppender,不是一对一
    • VanillaItemTagsProvider 现在实现 IntrinsicHolderTagsProvider
      • BlockToItemConverter - 一个将方块添加到物品标签的标签追加器。

通用编码与解码:替换直接 NBT 访问

从更高级别的对象(如实体和方块实体)中获取某些 NBT 数据的直接访问已被完全移除。这意味着,通常,在序列化过程中您不能直接接触 CompoundTag。相反,通过 ValueInputValueOutput 提供了对 nbt 标签的间接访问。顾名思义,它们分别从数据对象读取值和向数据对象写入值。可用的方法类似于 CompoundTag 上的方法。对于 ValueInput,有通过提供关联键的 get* 方法,以及如果不存在则获取或默认的 get*Or。还有用于处理 Codecread。对于 ValueOutput,有通过提供关联键和值的 put* 方法,以及用于 Codecstore。列表变体在输入/输出访问上单独存在。

因此,大多数接受 CompoundTag 的方法现在改为在 read/load 时接受 ValueInput,或在 write/save 时接受 ValueOutput

// 对于某个带有 ItemStack stack 的 Entity
@Override
protected void readAdditionalSaveData(ValueInput in) {
    super.readAdditionalSaveData(in);
    // 默认情况下,输入使用注册表 ops
    this.stack = in.read("example_stack", ItemStack.CODEC).orElse(ItemStack.EMPTY);
}

@Override
protected void addAdditionalSaveData(ValueOutput out) {
    super.addAdditionalSaveData(out);
    // 默认情况下,输出使用注册表 ops
    in.storeNullable("example_stack", ItemStack.CODEC, this.stack);
}

// 对于某个带有 int value 的 BlockEntity
@Override
    protected void loadAdditional(ValueInput in) {
        super.loadAdditional(in);
        this.value = in.getIntOr("value", 0);
    }

    @Override
    protected void saveAdditional(ValueOutput out) {
        super.saveAdditional(out);
        out.putInt("value", this.value);
    }

NBT 实现

为了提供对 CompoundTag 的间接访问,有分别称为 TagValueInputTagValueOutputValueInputValueOutput 的实现。

可以使用 createWithContextcreateWithoutContext 创建 TagValueOutput。“有上下文”意味着输出可以访问注册表对象的 HolderLookup$Provider,而“无上下文”则不能。目前,没有位置使用 createWithoutContext。内部会创建一个新的 CompoundTag。然后,这个输出被传递以填充,最后通过 buildResult 返回用于写入的 NBT。

另一方面,TagValueInput 可以通过 create 创建,接受 HolderLookup$Provider 和要读取的 CompoundTag。如果数据存储为对象列表而不是单个对象,您可以传入一个 List<CompoundTag> 并返回一个 ValueInputList。请注意,这不处理索引,只提供可迭代或流关联的实现。

问题报告器

除了上述内容之外,create* 方法还接受一个 ProblemReporter,用于收集在尝试序列化/反序列化数据时遇到的所有问题。由实现决定此报告是导致崩溃还是发出警告。一个 ProblemReporter 包含两个方法:report,用于报告一个 $Problem;以及 forChild,用于使用 $PathElement 进一步对 $Problem 进行分组。问题和路径元素都只是接口对象,分别返回指示问题是什么或分组的字符串。

有两个常用的 ProblemReporter$Collector,通常与数据提供者一起使用;以及 $ScopedCollector,与磁盘对象(例如,实体、方块实体、区块等)一起使用。$Collector 通常使用 forEach 逐个报告每个问题,getReport/getTreeReport 返回字符串化的问题,或 isEmpty 列出是否存在任何问题。$ScopedCollector 做同样的事情,只是它是 AutoCloseable,以防输出没有做任何操作。在这些情况下,报告会写入日志记录器。

每个收集器都接受一个初始的 $PathElement。这通常来自对象本身,其中包含某个称为 problemPath 的方法,该方法实现了该接口。HolderLookup$Provider 以相同的方式提供。

// 对于某个带有 HolderLookup.Provider registries 的对象
// 还有一个 Logger LOGGER

// 我们假设我们的根路径元素实现如下
public record ExamplePathElement(String name) implements ProblemReporter.PathElement {

    @Override
    public String get() {
        return "Example: " + this.name();
    }
}

// 对于数据提供者
ProblemReporter.Collector problems = new ProblemReporter.Collector(
    // 对于非指定的根,可以为空
    new ExamplePathElement("data_provider")
);
// 传递提供者

// 对于基于磁盘的对象
try (ProblemReporter.ScopedCollector problems = new ProblemReporter.ScopedCollector(new ExamplePathElement("EXAMPLE TEST"), LOGGER)) {
    TagValueOutput out = TagValueOutput.createWithContext(problems, this.registries);
    // 传递输出以写入数据

    // 对于输入
    // 最后一个参数可以是任何 CompoundTag,以输出为例
    TagValueInput in = TagValueInput.create(problems, this.registries, out.buildResult());
    // 传递输入以读取数据
}
  • net.minecraft.nbt.StringTag#escapeWithoutQuotes - 创建一个转义控制字符、引号、撇号和反斜杠的字符串。
  • net.minecraft.server.level.ServerPlayer
    • loadAndSpawnParentVehicle 现在接受一个 ValueInput
    • loadAndSpawnEnderPearls 现在接受一个 ValueInput
    • loadGameTypes 现在接受一个 ValueInput
  • net.minecraft.server.players.PlayerList#load 接受一个 ProblemReporter,返回一个可选的 ValueInput
  • net.minecraft.util.ProblemReporter
    • DISCARDING - 一个丢弃所有报告的报告器。
    • forChild 现在接受一个 $PathElement
    • report 现在接受一个 $Problem
    • $Collector 现在有一个接受根 $PathElement 的构造函数
      • isEmpty - 返回是否没有报告。
      • forEach - 遍历所有可用问题。
      • getReport 现在返回一个普通的 String
      • getTreeReport - 使用 DFS 获取报告及其所有子级。
    • $ElementReferencePathElement - 一个引用某个 ResourceKey 的路径元素。
    • $FieldPathElement - 一个引用某个字符串的路径元素。
    • $IndexedFieldPathElement - 一个在索引处引用某个字符串的路径元素。
    • $IndexedPathElement - 一个引用某个索引的路径元素。
    • $PathElement - 一个定义分组或元素的接口。
    • $Problem - 一个定义元素问题的接口。
    • $RootElementPathElement - 一个引用某个 ResourceKey 作为根的路径元素。
    • $RootFieldPathElement - 一个引用某个字符串作为根的路径元素。
    • $ScopedCollector - 一个在出现问题时记录警告的收集器。
  • net.minecraft.world
    • ContainerHelper
      • saveAllItems 现在接受一个 ValueOutput 而不是 CompoundTag,不再接受 HolderLookup$Provider,不返回任何内容
      • loadAllItems 现在接受一个 ValueInput 而不是 CompoundTag,不再接受 HolderLookup$Provider
    • LockCode#addToTagfromTag 现在接受 ValueOutput/ValueInput 而不是 CompoundTag,不再接受 HolderLookup$Provider
    • RandomziableContainer#tryLoadLootTabletrySaveLootTable 现在接受 ValueOutput/ValueInput 而不是 CompoundTag
    • SimpleContainer
      • fromTag -> fromItemList,不是一对一
      • createTag -> storeAsItemList,不是一对一
  • net.minecraft.world.entity
    • Entity
      • saveAsPassenger 现在接受一个 ValueOutput 而不是 CompoundTag
      • save 现在接受一个 ValueOutput 而不是 CompoundTag
      • saveWithoutId 现在接受一个 ValueOutput 而不是 CompoundTag,不返回任何内容
      • load 现在接受一个 ValueInput 而不是 CompoundTag
      • readAdditionalSaveData 现在接受一个 ValueInput 而不是 CompoundTag
      • addAdditionalSaveData 现在接受一个 ValueOutput 而不是 CompoundTag
      • problemPath - 返回报告问题的路径元素。
    • EntityRenference
      • store 现在接受一个 ValueOutput 而不是 CompoundTag
      • readreadWithOldOwnerConversion 现在接受一个 ValueInput 而不是 CompoundTag
    • Entity
      • UUID_TAG -> TAG_UUID
      • createby 现在接受一个 ValueInput 而不是 CompoundTag
      • loadEntityRecursive 现在接受一个 ValueInput 而不是 CompoundTag
      • loadEntitiesRecursive 现在接受一个 ValueInput$ValueInputList 而不是 nbt 标签列表
      • loadStaticEntity 现在接受一个 ValueInput 而不是 CompoundTag
    • EntityReference#store - 将引用数据写入 ValueOutput
    • Leashable#readLeashDatawriteLeashData 现在接受 ValueInput/ValueOutput 而不是 CompoundTag
    • LivingEntity#ATTRIBUTES_FIELD -> TAG_ATTRIBUTES
    • NeutralMob#addPersistentAngerSaveDatareadPersistentAngerSaveData 现在接受 ValueOutput/ValueInput 而不是 CompoundTag
  • net.minecraft.world.entity.npc.InventoryCarrier#readInventoryFromTagwriteInventoryToTag 现在接受 ValueInput/ValueOutput 而不是 CompoundTag
  • net.minecraft.world.entity.player.Inventory
    • save 现在接受一个 ValueOutput$TypedOutputList,不返回任何内容
    • load 现在接受一个 ValueOutput$TypedInputList
  • net.minecraft.world.entity.variant.VariantUtils
    • writeVariant 现在接受一个 ValueOutput 而不是 CompoundTag
    • readVariant 现在接受一个 ValueInput 而不是 CompoundTag,不再接受 RegistryAccess
  • net.minecraft.world.entity.vehicle.ContainerEntity#addChestVehicleSaveDatareadChestVehicleSaveData 现在接受 ValueOutput/ValueInput 而不是 CompoundTag,不再接受 HolderLookup$Provider
  • net.minecraft.world.inventory.PlayerEnderChestContainer
    • fromTag -> fromSlots,不是一对一
    • createTag -> storeAsSlots,不是一对一
  • net.minecraft.world.item
    • BlockItem#setBlockEntityData 现在接受一个 TagValueOutput 而不是 CompoundTag
    • ItemStack#parsesave 已移除
  • net.minecraft.world.level
    • BaseCommandBlock#saveload 现在接受 ValueOutput/ValueInput 而不是 CompoundTag,不再接受 HolderLookup$Provider,不返回任何内容
    • BaseSpawner#saveload 现在接受 ValueOutput/ValueInput 而不是 CompoundTag,不返回任何内容
  • net.minecraft.world.level.block.SculkSpreader#saveload 现在接受 ValueOutput/ValueInput 而不是 CompoundTag
  • net.minecraft.world.level.block.entity.BlockEntity
    • load* 方法现在接受 ValueInput 而不是 CompoundTag,不再接受 HolderLookup$Provider
    • save* 方法现在接受 ValueOutput 而不是 CompoundTag,不再接受 HolderLookup$Provider
    • removeComponentsFromTag 现在接受一个 ValueOutput 而不是 CompoundTag
    • parseCustomNameSafe 现在接受一个 ValueInput 和键,而不是标签和 HolderLookup$Provider
    • problemPath - 返回报告问题的路径元素。
  • net.minecraft.world.level.block.entity.trialspawner.TrialSpawner#loadstore - 处理写入生成器数据。
  • net.minecraft.world.level.chunk.ChunkAccess#problemPath - 返回报告问题的路径元素。
  • net.minecraft.world.level.storage
    • PlayerDataStorage#load 现在返回一个 ValueInput 而不是 CompoundTag,接受一个 ProblemReporter
    • TagValueInput - 一个复合标签输入。
    • TagValueOutput - 一个复合标签输出。
    • ValueInput - 一个定义如何从某个对象读取数据的接口。
    • ValueInputContextHelper - 一个包含用于读取对象数据的上下文的类。
    • ValueOutput - 一个定义如何向某个对象写入数据的接口。
  • net.minecraft.world.level.storage.loot.ValidationContext
    • forChildenterElement 现在接受 ProblemReporter$PathElement 而不是 String
    • reportProblem 现在接受 ProblemReporter$Problem 而不是 String
    • $MissingReferenceProblem - 一个引用对象缺失的问题。
    • $ParametersNotProvidedProblem - 一个战利品上下文参数缺失的问题。
    • $RecursiveReferenceProblem - 一个引用对象正在引用自身的问题。
    • $ReferenceNotAllowedProblem - 一个引用对象不允许被引用的问题。
  • net.minecraft.world.level.storage.loot.entries
    • AlternativesEntry#UNREACHABLE_PROBLEM - 一个替代条目永远无法执行的问题。
    • CompositeEntryBase#NO_CHILDREN_PROBLEM - 一个组合体没有条目的问题。
    • NestedLootTable#INLINE_LOOT_TABLE_PATH_ELEMENT - 一个表示表是内联的元素。

服务端玩家变更

MinecraftServer 不再在 ServerPlayer 上公开。此外,serverLevel 已被移除,现在用重载的 level 来返回 ServerLevel

  • net.minecraft.server.level.ServerPlayer
    • server 字段现在是私有的
    • serverLevel -> level,仍然返回 ServerLevel

小幅迁移

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

拴绳

拴绳系统已更新,最多支持四个拴绳同时拴在一个实体上。此外,物理效果已更新,以更恰当地处理某些可拉伸物体的现实弹性。

  • net.minecraft.client.renderer.entity.state.EntityRenderState
    • leashState 现在返回一个 $LeashState 列表
    • $LeashState#slack - 拴绳是否有松弛。
  • net.minecraft.world.entity
    • Entity
      • shearOffAllLeashConnections - 处理使用剪刀移除拴绳时的情况。
      • dropAllLeashConnections - 处理应从实体移除所有拴绳时的情况。
      • getQuadLeashHolderOffsets - 获取四个拴绳拴在实体上时的偏移量。
      • supportQuadLeashAsHolder - 返回实体是否可以被拴最多四次。
      • notifyLeashHoldernotifyLeasheeRemoved - 处理拴绳在实体上Tick以及被移除时的情况。
      • setLeashOffset 已移除
      • getLeashOffset -> Leashable#getLeashOffset
    • Leashable
      • MAXIMUM_ALLOWED_LEASHED_DIST - 拴绳可以拴到实体的最大距离。
      • AXIS_SPECIFIC_ELASTICITY - 拴绳沿每个轴的阻力。
      • SPRING_DAMPENING - 拴绳拉伸时振荡的能量损失。
      • TORSIONAL_ELASTICITY - 拴绳在扭矩下的阻力。
      • STIFFNESS - 拴绳的刚度。
      • ENTITY_ATTACHMENT_POINT - 指定拴绳在实体上的附着点。
      • LEASHER_ATTACHMENT_POINT - 指定拴绳在持有者上的附着点。
      • SHARED_QUAD_ATTACHMENT_POINTS - 指定拴绳在实体上的附着点。
      • canHaveALeashAttachedToIt -> canHaveALeashAttachedTo,不是一对一
      • leashDistanceTo - 返回拴绳在持有者和被拴者之间经过的距离。
      • onElasticLeashPull - 处理拴绳被拉拽时的情况。
      • leashSnapDistance - 返回拴绳将尝试从实体上移除的距离。
      • leashElasticDistance - 返回拴绳的弹性成为物理因素之前的最大距离。
      • handleLeashAtDistance 已移除
      • angularFriction - 返回实体在方块上或液体中的角摩擦。
      • whenLeashedTo - 通知实体拴绳已附着。
      • elasticRangeLeashBehaviourlegacyElasticRangeLeashBehaviour -> checkElasticInteractions,不是一对一
      • supportQuadLeash - 实体是否可以被拴最多四次。
      • getQuadLeashOffsets - 返回附着在实体上的每个拴绳的偏移量。
      • createQuadLeashOffsets - 为四个可能的拴绳位置中的每一个创建偏移量。
      • leashableLeashedTo - 获取所有在 32 格半径内被拴到此持有者的实体。
      • $LeashData#angularMomentum - 返回实体被拴时的角动量。
      • $Wrench - 一个记录,处理施加在拴绳上的力和扭矩。
  • net.minecraft.world.item.LeadItem#leashableInArea -> Leashable#leashableInArea

移除生物效果图集

生物效果图集已被移除,并与 GUI 图集合并。

  • net.minecraft.client.Minecraft#getMobEffectTextures 已移除
  • net.minecraft.client.gui.Gui#getMobEffectSprite - 获取状态效果精灵的位置。
  • net.minecraft.client.resources.MobEffectTextureManage 类已移除
  • AtlasIds#MOB_EFFECTS 已移除

权限来源

命令的权限检查已被抽象到其自己的 PermissionSource 接口中。这提供了之前提供的 hasPermission 方法,以及一个新方法 allowsSelectors,它返回源是否有选择其他实体所需的权限(默认为 2 级权限)。您可以通过在 ArgumentBuilder#requires 中使用所需的级别调用 Commands#hasPermission,将权限检查合并到您的命令中。

  • net.minecraft.client.multiplayer
    • ClientPacketListener
      • getCommands 现在返回一个 ClientSuggestionProvider 泛型
      • sendUnattendedCommand 现在接受一个 Screen 而不是 boolean
    • ClientSuggestionListener 现在实现 PermissionSource,接受一个布尔值表示是否允许受限命令
      • allowRestrictedCommands - 返回是否建议受限命令。
  • net.minecraft.commands
    • Commands#hasPermission - 返回给定级别的权限检查。
    • CommandSourceStack 现在实现 PermissionSource
    • ExecutionCommandSource 现在实现 PermissionSource
    • PermissionSource - 返回运行命令的权限源。
    • SharedSuggestionProvider
      • suggestResgitryElements 现在接受 HolderLookup 而不是 Registry
      • listSuggestions - 列出某些注册表元素的建议。
      • hasPermission 已移除
  • net.minecraft.commands.synchronization.SuggestionProviders
    • AVAILABLE_SOUNDSSUMMONABLE_ENTITIES 现在接受 SharedSuggestionProvider 作为其泛型
    • cast - 将建议提供者转换为正确的类型。
    • safelySwap 已移除
    • $Wrapper -> $RegisteredSuggestion
  • net.minecraft.world.entity.Entity#getCommandSenderWorld 已移除

动画烘焙

动画现在被烘焙到 KeyframeAnimation 中。每个 KeyframeAnimation 由将关键帧应用于给定 ModelPart 的条目组成。要创建动画,应在模型构造函数中通过 AnimationDefinition#bake 烘焙定义,然后在 EntityModel#setupAnim 期间根据需要调用 #apply#applyWalk

// 对于某个实体模型
// 假设存在某个 AnimationDefinition EXAMPLE_DEFN
// 假设我们的 ExampleEntityState 有一个 AnimationState exampleAnimState
public class ExampleModel extends EntityModel<ExampleEntityState> {

    private final KeyframeAnimation exampleAnim;

    public ExampleModel(ModelPart root) {
        // 我们传入任何可以应用所有动画的 'root'
        this.exampleAnim = EXAMPLE_DEFN.bake(root);
    }

    @Override
    public void setupAnim(ExampleEntityState state) {
        super.setupAnim(state);
        this.exampleAnim.apply(state.exampleAnimState, state.ageInTicks);
    }
}
  • net.minecraft.client.animation
    • AnimationDefinition#bake - 烘焙一个已定义的动画,以便在 Model 上使用。
    • KeyframeAnimation - 一个用于在给定 Model 上移动 ModelPart 的烘焙动画。
    • KeyframeAnimations#animate -> KeyframeAnimation$Entry#apply
  • net.minecraft.client.model.Model
    • getAnyDescendantWithName 已移除
    • animate -> KeyframeAnimation#apply
    • animateWalk - KeyframeAnimation#applyWalk
    • applyStatic -> KeyframeAnimation#applyStatic
  • net.minecraft.client.model.geom.ModelPart
    • getAllParts 现在返回一个 List
    • createPartLookup - 创建一个部件名称到其 ModelPart 的查找表,任何重复的名称将被忽略。

ChunkSectionLayers

用于定义方块或流体应如何渲染的 RenderType 现在已被 ChunkSectionLayer 取代。它们在功能上与 RenderType 相同;然而,它们只指定要使用的 RenderPipeline 以及缓冲区信息。这也意味着某些 RenderType 被移除,例如 TRANSLUCENT,因为它们仅用于区块渲染。

这也意味着添加到 ItemBlockRenderTypes#TYPE_BY_BLOCK 必须指定 ChunkSectionLayer 而不是关联的 RenderType

  • net.minecraft.client.renderer
    • ItemBlockRenderTypes
      • getChunkRenderType 现在返回一个 ChunkSectionLayer
      • getRenderLayer(FluidState) 现在返回一个 ChunkSectionLayer
    • RenderType
      • translucent 已移除
      • getRenderTargetgetRenderPipeline 已移除
      • chunkBufferLayers 已移除
  • net.minecraft.client.renderer.chunk
    • ChunkSectionLayer - 一个枚举,定义如何渲染单个区块层(例如,实心方块、半透明方块)。
    • ChunkSectionLayerGroup - 一个枚举,将层分组以进行渲染。
    • ChunkSectionsToRender - 一个记录,包含给定区块的绘制,允许按层组渲染它们。
    • RenderChunk -> SectionCopy
    • RenderChunkRegion -> RenderSectionRegion
    • RenderRegionCache#createRegion 现在接受一个 long 而不是 SectionPos
    • SectionCompiler$Results
      • globalBlockEntities -> - net.minecraft.client.multiplayer.ClientLevel#getGloballyRenderedBlockEntities
      • renderedLayers 现在接受 ChunkSectionLayer 作为键
    • SectionMesh - 一个定义区块内给定部分的网格的接口
    • SectionRenderDispatcher
      • getBatchToCount -> getCompileQueueSize
      • setCameragetCameraPosition 已移除
      • blockUntilClear 已移除
      • clearBatchQueue -> clearCompileQueue,现在是公开的
      • $CompiledSection -> CompiledSectionMesh
      • $RenderSection
        • getBuffers 已移除
        • uploadSectionLayer(RenderType, MeshData) -> upload(Map, CompiledSectionMesh),不是一对一
        • uploadSectionIndexBuffer 现在接受一个 CompiledSectionMesh 和一个 ChunkSectionLayer 而不是 RenderType
        • getDistToPlayerSqr 已移除
        • getCompiled -> getSectionMesh,不是一对一
        • rebuildSectionAsync 不再接受 SectionRenderDispatcher
        • setDynamicTransformIndexgetDynamicTransformIndex 已移除
      • $SectionBuffers -> SectionBuffers
      • $TranslucencyPointOfView -> TranslucencyPointOfView
  • net.minecraft.server.level.ChunkMap#getUpdatingChunkIfPresent 现在是公开的
  • net.minecraft.world.level.TicketStorage
    • purgeStaleTickets 现在接受 ChunkMap
    • removeTicketIf 现在接受一个 BiPredicate 而不是 Predicate,接受区块位置和加载票
  • net.minecraft.world.level.chunk.ChunkAccess#isSectionEmpty 已移除

标签变更

  • minecraft:block
    • plays_ambient_desert_block_sounds 拆分为 triggers_ambient_desert_sand_block_soundstriggers_ambient_desert_dry_vegetation_block_sounds
    • happy_ghast_avoids
    • triggers_ambient_dried_ghast_block_sounds
  • minecraft:dialog
    • pause_screen_additions
    • quick_actions
  • minecraft:entity_type
    • can_equip_harness
    • followable_friendly_mobs
  • minecraft:item
    • harnesses
    • happy_ghast_food
    • happy_ghast_tempt_items

新增列表

  • com.mojang.blaze3d.pipeline
    • BlendFunction#TRANSLUCENT_PREMULTIPLIED_ALPHA - 一个假设目标具有来自合成步骤的预乘 alpha 的混合函数。
    • RenderPipeline
      • getSortKey - 返回一个表示元素应如何排序以进行渲染的值。用于层排序。
      • updateSortKeySeed - 更新排序键的种子,当前未使用。
  • com.mojang.blaze3d.systems.RenderSystem
    • outputColorTextureOverride - 持有一个包含覆盖颜色的纹理,该覆盖颜色将代替 RenderType 目标中指定的任何内容使用。
    • outputDepthTextureOverride - 持有一个包含覆盖深度的纹理,该覆盖深度将代替 RenderType 目标中指定的任何内容使用。
  • com.mojang.blaze3d.textures.GpuTexture#setUseMipmaps - 设置纹理在不同距离是否应使用 mipmap。
  • net.minecraft
    • FileUtil#isPathPartPortable - 返回提供的字符串是否与任何 Windows 保留文件名不匹配。
    • WorldVersion$Simple - 当前世界版本的简单实现。
  • net.minecraft.advancements.critereon
    • ItemUsedOnLocationTrigger$TriggerInstance#placedBlockWithProperties - 创建一个触发器,其中放置了一个具有指定属性的方块。
    • PlayerInteractTrigger$TriggerInstance#equipmentSheared - 创建一个条件触发器,作用于玩家从某个实体上取下物品。
  • net.minecraft.client
    • GameNarrator#saySystemChatQueued - 如果启用了系统或聊天消息旁白,则旁白一个组件。
    • Minecraft#disconnectWithSavingScreen - 断开当前客户端实例并显示“保存等级”屏幕。
    • Options
      • keyQuickActions - 用于显示快速操作对话框的按键映射。
      • cloudRange - 返回云可以渲染的最大距离。
      • musicFrequency - 返回 MusicManager 处理的背景音乐应播放的频率。
      • showNowPlayingToast - 返回是否显示“正在播放”吐司。
      • getFinalSoundSourceVolume - 计算给定声音源的音量,非主声音源由主声音源缩放。
    • NarratorStatus#shouldNarrateSystemOrChat - 返回当前旁白状态是否为除 OFF 之外的任何状态。
  • net.minecraft.client.color.ColorLerper - 一个基于部分刻在颜色类型之间进行插值的实用工具类。
  • net.minecraft.client.data.models.BlockModelGenerators#createDriedGhastBlock - 创建干燥恶魂方块模型定义。
  • net.minecraft.client.data.models.model
    • ModelTemplates#DRIED_GHAST - 一个使用 minecraft:block/dried_ghast 父级的模板。
    • TextureMapping#driedGhast - 为干燥恶魂模型创建默认纹理映射。
    • TextureSlot#TENTACLES - 提供一个纹理键 tentacles
  • net.minecraft.client.model
    • GhastModel#animateTentacles - 动画恶魂的触手。
    • HappyGhastHarnessModel - 一个代表恶魂挽具的模型。
    • HappyGhastModel - 一个代表“驯服”恶魂的模型。
    • QuadrupedModel#createBodyMesh 现在接受两个布尔值,分别用于处理左后腿和右后腿纹理是否镜像。
  • net.minecraft.client.multiplayer.ClientLevel
    • DEFAULT_QUIT_MESSAGE - 持有退出游戏文本的组件。
    • disconnect(Copmonent) - 断开与当前等级实例的连接,显示关联的组件。
  • net.minecraft.client.renderer.entity.HappyGhastRenderer - “驯服”恶魂的渲染器。
  • net.minecraft.client.renderer.entity.layers.RopesLayer - 用于“驯服”恶魂上的绳索的渲染层。
  • net.mienecraft.client.renderer.entity.state.HappyGhastRenderState - “驯服”恶魂的状态。
  • net.minecraft.client.resources.model.EquipmentclientInfo$LayerType#HAPPY_GHAST_BODY - 一个代表快乐恶魂身体的层。
  • net.minecraft.client.resources.sounds.RidingHappyGhastSoundInstance - 一个在骑乘快乐恶魂时播放的可Tick声音实例。
  • net.minecraft.client.sounds
    • MusicManager
      • getCurrentMusicTranslationKey - 返回当前正在播放的音乐的翻译键。
      • setMinutesBetweenSongs - 设置背景曲目之间的频率。
      • showNowPlayingToastIfNeeded - 如果需要,显示正在播放吐司。
      • $MusicFrequency - 正在播放的背景曲目的频率。
    • SoundEngine$PlayResult - 尝试播放的声音的起始状态。
  • net.minecraft.commands.arguments
    • HexColorArgument - 一个接受十六进制颜色的整数参数。
    • ResourceOrIdArgument
      • createGrammar - 创建用于解析参数的语法。
      • $InlineResult - 一个返回直接持有者的结果。
      • $ReferenceResult - 一个返回引用持有者的结果。
      • $Result - 一个表示某个参数解析结果的接口。
  • net.minecraft.data.loot.LootTableProvider$MissingTableProblem - 一个记录,保存某个缺失的内置表生成器的键。
  • net.minecraft.data.recipes.RecipeProvider
    • dryGhast - 干燥恶魂的配方。
    • harness - 染色挽具的配方。
  • net.minecraft.gametest.framework.GameTestTicker#startTicking - 开始为游戏测试Tick运行器。
  • net.minecraft.nbt.NbtUtils
    • addCurrentDataVersionaddDataVersion,将数据版本添加到某个 nbt 标签。
  • net.minecraft.network.FriendlyByteBuf#writeEitherreadEither - 使用给定的流编码器/解码器处理 Either
  • net.minecraft.network.codec.ByteBufCodecs
    • RGB_COLOR - 一个使用三个字节写入 RGB 的流编解码器。
    • lenientJson - 创建一个以宽松模式解析 json 的流编解码器。
    • optionalTagCodec - 创建一个使用提供的 NbtAccounter 解析 Optional 包装的 Tag 的流编解码器。
  • net.minecraft.network.protocol.game
    • ServerboundChangeGameModePacket - 更改当前游戏模式。
    • ServerboundCustomClickActionPacket - 在服务器上执行自定义操作,目前什么都不做。
  • net.minecraft.server.MinecraftServer#handleCustomClickAction - 处理从点击事件发送的自定义操作。
  • net.minecraft.server.level.ServerLevel
    • updateNeighboursOnBlockSet - 更新当前位置的邻居。如果方块不相同(不包括其属性),则调用 BlockState#affectNeighborsAfterRemoval
    • waitForChunkAndEntities - 添加一个任务,使服务器等待,直到实体在提供的区块范围内加载。
  • net.minecraft.sources.SoundSource#UI - 来自某些用户界面的声音。
  • net.minecraft.stats
    • RecipeBookSettings#MAP_CODEC
    • ServerRecipeBook#packloadUntrusted$Packed - 处理编码和解码配方书的数据。
  • net.minecraft.util
    • ARGB
      • setBrightness - 使用 0 到 1 之间的浮点数返回某个颜色的亮度。
      • color - 从浮点红色和整数 alpha 返回一个 ARGB 颜色。
    • ExtraCodecs
      • VECTOR2F
      • VECTOR3I
      • NBT
    • LenientJsonParser - 一个使用宽松规则的 json 解析器。
    • Mth#smallestSquareSide - 取一个数的平方根的上取整。
    • StrictJsonParser - 一个使用严格规则的 json 解析器。
  • net.minecraft.world
    • Difficulty#STREAM_CODEC
    • ItemStackWithSlot - 一个记录,包含一个堆栈及其槽位索引。
  • net.minecraft.world.entity
    • Entity
      • MAX_MOVEMENTS_HANDELED_PER_TICK - 在给定Tick中可以应用于实体的最大移动数。
      • isInClouds - 返回实体的 Y 位置是否在云高度和其上方四个单位之间。
      • teleportSpectators - 传送当前从玩家视角观看的旁观者。
      • isFlyingVehicle - 返回载具是否可以飞行。
      • clearMovementThisTick - 清除实体在本Tick中将进行的所有移动。
    • EntityAttachments#getAverage - 返回所有附着点的平均位置。
    • ExperienceOrb
      • awardWithDirection - 添加一个通过指定向量移动的经验球。
      • unstuckIfPossible - 尝试查找并将球移动到空闲位置。
    • Mob
      • isWithinHome - 返回该位置是否在实体的限制半径内。
      • canShearEquipment - 返回当前玩家是否可以从该生物上剪下装备。
  • net.minecraft.world.entity.ai.control.MoveControl#setWait - 将操作设置为 WAIT
  • net.minecraft.world.entity.ai.goal.TemptGoal
    • stopNavigationnavigateTowards - 处理向玩家的导航。
    • $ForNonPathfinders - 一个引诱目标,它导航到想要的位置,而不是立即寻路。
  • net.minecraft.world.entity.ai.navigation.PathNavigation#canNavigateGround - 返回实体是否可以在陆地上寻路。
  • net.minecraft.world.entity.ai.sensing.AdultSensorAnyType - 一个忽略实体是否与幼崽相同类型的成年传感器。
  • net.minecraft.world.entity.animal
    • HappyGhast - 一个代表快乐恶魂的实体。
    • HappyGhastAi - 快乐恶魂的大脑。
  • net.minecraft.world.entity.decoration.ArmorStand
    • setArmorStandPosegetArmorStandPose$ArmorStandPose - 处理盔甲架的姿势。
  • net.minecraft.world.entity.monster.Ghast
    • faceMovementDirection - 旋转实体以面对其当前移动方向。
    • $RandomFloatAroundGoal#getSuitableFlyToPosition - 获取恶魂应飞向的位置。
  • net.minecraft.world.entity.player.Inventory#SLOT_BODY_ARMORSLOT_SADDLE - 相应槽位的索引。
  • net.minecraft.world.entity.projectile.ProjectileUtil#computeMargin - 根据其Tick计数计算要检查的给定实体的边界框边距。
  • net.minecraft.world.item.component
    • ItemAttributeModifiers
      • forEach - 将消费者应用于槽位组内的所有属性。
      • $Builder#add - 添加一个要应用于给定槽位组的属性,并带有显示。
      • $Display - 定义属性修改器应如何在其工具提示中显示。
      • $Default - 显示默认属性显示。
      • $Hidden - 不显示任何属性信息。
      • $OverrideText - 用提供的组件覆盖属性文本。
    • Equippable$Builder
      • setCanBeSheared - 设置装备是否可以从实体上剪下。
      • setShearingSound - 设置从实体上剪下一件装备时要播放的声音。
    • ResolvableProfile#pollResolve - 返回存储的 id 或名称的配置文件。
  • net.minecraft.world.item.equipment.Equippable#harness - 表示要装备的挽具。
  • net.minecraft.world.level
    • CollisionGetter
      • getPreMoveCollisions - 返回一个包含给定边界框和未来移动方向上的实体和方块碰撞的形状的可迭代对象。
      • getBlockCollisionsFromContext - 从给定的碰撞上下文中获取方块形状。
    • GameType#STREAM_CODEC
    • Level
      • precipitationAt - 返回给定位置的降水。
      • onBlockEntityAdded - 当方块实体被添加到等级时要运行的逻辑。
  • net.minecraft.world.level.block
    • BaseRailBlock#rotate - 在关联方向上旋转当前的铁轨形状。
    • DriedGhastBlock - 一个代表干燥恶魂的方块。
  • net.minecraft.world.level.block.entity.trialspawner.TrialSpawner$FullConfig - 代表试炼的整个配置。
  • net.minecraft.world.level.dimension.DimensionDefaults
    • CLOUD_THICKNESS - 云的方块厚度。
    • OVERWORLD_CLOUD_HEIGHT - 主世界的云高度等级。
  • net.minecraft.world.level.levelgen.flat.FlatLayerInfo#heightLimited - 返回一个新的层信息,当前高度是否限制为指定值,只要该值不在最大范围内。
  • net.minecraft.world.phys
    • AABB
      • intersects - 返回 BlockPos 是否与此框相交。
      • distanceToSqr - 返回边界框从其最远点的平方距离。
    • Vec3#rotateClockwise90 - 将向量顺时针旋转 90 度(翻转 x 和 z 并反转新的 x 值)。
  • net.minecraft.world.phys.shapes.CollisionContext
    • withPosition - 返回实体的碰撞上下文及其底部 y 位置。

变更列表

  • com.mojang.blaze3d.platform.Window#setGuiScalegetGuiScale 现在处理 int 而不是 double
  • net.mineraft
    • DetectedVersion 不再实现 WorldVersion
    • WorldVersion 方法由于使用 WorldVersion$Simple 而使用记录命名模式
      • getDataVersion -> dataVersion
      • getId -> id
      • getName -> name
      • getProtocolVersion -> protocolVersion
      • getPackVersion -> packVersion
      • getBuildTime -> buildTime
      • isStable -> stable
  • net.minecraft.client
    • GameNarrator
      • sayChat -> sayChatQueued
      • say -> saySystemQueued
      • sayNow -> saySystemNow
    • Minecraft
      • grabPanoramixScreenshot 不再接受要设置的窗口宽度和高度
      • disconnect() -> disconnectWithProgressScreen
    • Screenshot#grabtakeScreenshot 现在接受一个表示缩小因子的 int
  • net.minecraft.client.main.GameConfig$QuickPlayData 现在接受一个 $QuickPlayVariant
    • path -> logPath
    • singleplayer -> variant 带有 $QuickPlaySinglePlayerData
    • multiplayer -> variant 带有 $QuickPlayMultiplayerData
    • realms -> variant 带有 $QuickPlayRealmsData
    • 对于 singleplayermultiplayerrealms 的 null 由带有 $QuickPlayDisabledvariant 表示
  • net.minecraft.client.data.models.ItemModelGenerators#generateWolfArmor -> generateTwoLayerDyedItem
  • net.minecraft.client.gui.components.DebugScreenOverlay#render3dCrosshair 现在接受当前的 Camera
  • net.minecraft.client.gui.components.debugchart.ProfilerPieChart
    • RADIUS 现在是公开的
    • CHART_Z_OFFSET -> PIE_CHART_THICKNESS,现在是公开的
  • net.minecraft.client.multiplayer
    • ClientLevel$ClientLevelData#getClearColorScale -> voidDarknessOnsetRange,不是一对一
    • MultiPlayerGameMode#createPlayer 现在接受一个 Input 而不是 boolean
  • net.minecraft.client.player.LocalPlayer 现在接受最后发送的 Input 而不是 shift 键的 boolean
    • getLastSentInput - 获取从服务器最后发送的输入。
  • net.minecraft.client.quickplay.QuickPlay#connect 现在接受 GameConfig$QuickPlayVariant 而不是 GameConfig$QuickPlayData
  • net.minecraft.client.renderer
    • DimensionSpecialEffects 不再接受当前云级别以及是否有地面
    • LightTexture#getTarget -> getTexture
  • net.minecraft.client.renderer.blockentity.BlockEntityRenderer#shouldRenderOffscreen 不再接受 BlockEntity
  • net.minecraft.client.resources
    • AbstractSoundInstance#sound 现在是 Nullable
    • SoundInstance#getSound 现在是 Nullable
  • net.minecraft.client.sounds
    • SimpleSoundInstance#forMusic 现在也接受 float 音量
    • SoundEngine 现在接受 MusicManager
      • pause -> pauseAllExcept,不是一对一
      • play 现在返回一个 $PlayResult
    • SoundManager 现在接受 MusicManager
      • pause -> pauseAllExcept,不是一对一
      • play 现在返回一个 SoundEngine$PlayResult
  • net.minecraft.commands.arguments
    • ResourceOrIdArgument 现在接受一个任意编解码器,而不是 Holder 包装的值
      • ERROR_INVALID -> ERROR_NO_SUCH_ELEMENT,现在是公开的,不是一对一
      • VALUE_PARSER -> OPS,现在是公开的,不是一对一
    • ResourceSelectorArgument#getSelectedResources 不再接受 ResourceKey
  • net.minecraft.commands.functions.StringTemplate
    • fromString 不再接受行号
    • isValidVariableName 现在是公开的
  • net.minecraft.data.recipes.RecipeProvider#colorBlockWithDye -> colorItemWithDye,现在接受 RecipeCategory
  • net.minecraft.gametest.framework.GameTestInfo#prepareTestStructure 现在可为 null
  • net.minecraft.network
    • Connection#send 现在接受一个 ChannelFutureListener 而不是 PacketSendListener
    • FriendlyByteBuf#readJsonWithCodec -> readLenientJsonWithCodec
    • PacketSendListener 现在是一个类,其方法返回 ChannelFutureListener 而不是 PacketSendListener
      • onSuccessonFailure 已移除
  • net.minecraft.network.codec
    • ByteBufCodecs#fromCodec 现在有一个接受某些 ops 和一个编解码器的重载
    • StreamCodec#composite 现在有一个接受十个参数的重载
  • net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket 现在是一个记录
  • net.minecraft.network.protocol.game
    • ClientboundChangeDifficultyPacket 现在是一个记录
    • ClientboundCommandsPacket 现在接受一个 $NodeInspector
      • getRoot 现在是泛型的,接受一个 $NodeBuilder
      • $NodeBuilder - 一个给定命令的构建器。
      • $NodeInspector - 一个检查给定命令节点信息的代理。
    • ServerboundChangeDifficultyPacket 现在是一个记录
  • net.minecraft.server.ReloadableServerRegistries$Holder#lookup 返回一个 HolderLookup$Provider
  • net.minecraft.server.network.ServerCommonPacketListenerImpl#send 现在接受一个 ChannelFutureListener 而不是 PacketSendListener
  • net.minecraft.sounds.Music 现在是一个记录
  • net.minecraft.stats.RecipeBookSettings
    • getSettings 现在是公开的
    • $TypeSettings 现在是公开的
  • net.minecraft.world.entity
    • AreaEffectCloud#setParticle -> setCustomParticle
    • Entity
      • checkSlowFallDistance -> checkFallDistanceAccumulation
      • collidedWithFluidcollidedWithShapeMovingFrom 现在是公开的
      • canBeCollidedWith 现在接受与其碰撞的实体
      • spawnAtLocation 现在有一个接受 Vec3 作为偏移位置的重载
      • removeLatestMovementRecordingBatch -> removeLatestMovementRecording
    • EntityReference 现在是 final
    • ExperienceOrb 现在有一个接受两个向量作为位置和移动的重载
    • FlyingMob 被调用 LivingEntity#travelFlying 取代
    • LivingEntity#canBreatheUnderwater 不再是 final
    • Mob
      • restrictTo -> setHomeTo
      • getRestrictCenter -> getHomePosition
      • getRestrictRadius -> getHomeRadius
      • clearRestriction -> clearHome
      • hasRestriction -> hasHome
  • net.minecraft.world.entity.ai.attributes
    • AttributeInstance
      • save -> pack$Packed;不是一对一
      • load -> apply,不是一对一
    • AttributeMap
      • save -> pack;不是一对一
      • load -> apply,不是一对一
  • net.minecraft.world.entity.ai.behavior
    • AnimalPanic 现在有接受半径或位置获取器的重载
    • BabyFollowAdult#create 现在返回一个 OneShot<LivingEntity>,并且可以接受一个 boolean 表示是否瞄准眼睛位置
    • EntityTracker 现在可以接受一个 boolean 表示是否瞄准眼睛位置
    • FollowTemptation 现在有一个重载,检查实体是否需要跟踪实体的眼睛高度。
  • net.minecraft.world.entity.ai.goal.TemptGoal 现在有一个接受停止距离的重载
    • mob 现在是一个 Mob
    • speedModifier 现在是 protected
  • net.minecraft.world.entity.ai.memory.MemoryModuleType#NEAREST_VISIBLE_ADULT 现在持有 LivingEntity
  • net.minecraft.world.entity.ai.navigation
    • FlyingPathNavigationGroundPathNavigation#setCanOpenDoors -> PathNavigation#setCanOpenDoors
  • net.minecraft.world.entity.ai.sensing.AdultSensor 现在查找 LivingEntity
    • setNearestVisibleAdult 现在是 protected
  • net.minecraft.world.entity.animal.*Variants#selectVariantToSpawn -> entity.variant.VariantUtils#selectVariantToSpawn,不是一对一
  • net.minecraft.world.entity.animal.Fox#isJumping -> LivingEntity#isJumping
  • net.minecraft.world.entity.animal.horse.AbstractHorse
    • isJumping -> LivingEntity#isJumping
    • setStanding 现在接受一个 int 而不是 boolean 作为站立计数器
      • false 逻辑已移至 clearStanding
  • net.minecraft.world.entity.monster
    • Ghast 现在实现 Mob
      • $GhastLookGoal 现在是公开的,接受一个 Mob
      • $GhastMoveControl 现在是公开的,接受一个布尔值表示移动时是否应小心,以及一个提供的布尔值表示恶魂是否应停止移动
      • $RandomFloatAroundGoal 现在是 public,接受一个 Mob 和一个方块距离
    • Phantom 现在实现 Mob
  • net.minecraft.world.entity.player
    • Abilities
      • addSaveData -> pack$Packed;不是一对一
      • loadSaveData -> apply,不是一对一
    • Player 不再接受 BlockPos 和 y 旋转
  • net.minecraft.world.entity.projectile
    • AbstractThrownPotion#onHitAsPostion 现在接受一个 HitResult 而不是可为 null 的 Entity
    • EyeOfEnder#signalTo 现在接受一个 Vec3 而不是 BlockPos
    • Projectile
      • ownerUUIDcachedOwner -> owner,现在是 protected;不是一对一
      • setOwner 现在有一个接受 EntityReference 的重载
    • ProjectileUtil
      • DEFAULT_ENTITY_HIT_RESULT_MARGIN 现在是公开的
      • getEntityHitResult 现在接受一个 Projectile 而不是 Entity
  • net.minecraft.world.item.ItemStack
    • forEachModifier 现在接受一个提供修改器显示的 TriConsumer
    • hurtAndBreak 现在有一个重载,从 InteractionHand 获取 EquipmentSlot
  • net.minecraft.world.item.equipment.Equippable 现在接受装备是否可以从实体上剪下以及剪下时要播放的声音
  • net.minecraft.world.level.BlockGetter
    • forEachBlockIntersectedBetween 现在返回一个布尔值,表示在相交区域中访问的每个方块是否可以成功访问
    • $BlockStepVisitor#visit 现在返回是否可以成功移动到该位置
  • net.minecraft.world.level.block.AbstractCauldronBlock#SHAPE 现在是 protected
  • net.minecraft.world.level.block.entity
    • BlockEntity#getNameForReporting 现在是公开的
    • SignBlockEntity#executeClickCommandsIfPresent 现在接受一个 ServerLevel 而不是 Level,参数重新排序
    • StructureBlockEntity#saveStructure 现在接受一个要忽略的方块列表
  • net.minecraft.world.level.block.entity.trialspawner
    • TrialSpawner 现在接受一个 $FullConfig
      • getConfig -> activeConfig
      • get*Config -> *config
      • getData -> getStateData
    • TrialSpawnerData -> TrialSpawnerStateData,序列化形式为 TrialSpawnerStateData$Packed,不是一对一
  • net.minecraft.world.level.block.sounds.AmbientDesertBlockSoundsPlayer#playAmbientBlockSounds 已拆分为 playAmbientSandSoundsplayAmbientDryGrassSoundsplayAmbientDeadBushSoundsshouldPlayDesertDryVegetationBlockSounds;不是一对一
  • net.minecraft.world.level.dimension.DimensionType 现在接受一个可选的整数表示云高度等级
  • net.minecraft.world.level.entity
    • PersistentEntitySectionManager#processPendingLoads 现在是公开的
    • UUIDLookup#getEntity 现在可以返回 null
  • net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate#fillFromWorld 现在接受一个要忽略的方块列表,而不是单个 Block
  • net.minecraft.world.level.storage.DataVersion 现在是一个记录
  • net.minecraft.world.phys.shapes.CollisionContext#placementContext 现在接受一个 Player 而不是 Entity

移除列表

  • net.minecraft.client.Minecraft#disconnect(Screen)
  • net.minecraft.client.renderer
    • DimensionSpecialEffects#getCloudHeighthasGround
    • LevelRenderer#updateGlobalBlockEntities
  • net.minecraft.client.renderer.texture.AbstractTexture
    • defaultBlur
    • setFilter
  • net.minecraft.network.chat.Component$Serializer$SerializerAdapter
  • net.minecraft.network.protocol.game.ServerboundPlayerCommandPacket$Action#*_SHIFT_KEY
  • net.minecraft.server.ReloadableServerRegistries$Holder#getKeys
  • net.minecraft.server.players.PlayerList#getPlayerForLogin
  • net.minecraft.stats
    • RecipeBookSettings#readwrite
    • ServerRecipeBook#toNbtfromNbt
  • net.minecraft.util
    • GsonHelper#fromNullableJson(..., boolean)fromJson(..., boolean)
    • LowerCaseEnumTypeAdapterFactory
  • net.minecraft.world.entity.ai.attributes.AttributeInstance#ID_FIELDTYPE_CODEC
  • net.minecraft.world.entity.animal.horse.AbstractHorse#setIsJumping
  • net.minecraft.world.entity.animal.sheep.Sheep#getColor
  • net.minecraft.world.entity.monster.Drowned#waterNavigationgroundNavigation
  • net.minecraft.world.entity.projectile.Projectile#findOwnersetOwnerThroughUUID
  • net.minecraft.world.level.Level#disconnect()
  • net.minecraft.world.level.block
    • AbstractCauldronBlock#isEntityInsideContent
    • TerracottaBlock
  • net.minecraft.world.level.block.entity.trialspawner.TrialSpawner
    • *_CONFIG_TAG_NAME
    • codec
  • net.minecraft.world.level.dimension.DimensionType#parseLegacy

Minecraft 1.21.6 -> 1.21.7 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

小幅迁移

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

新增列表

  • com.mojang.blaze3d.opengl.DirectStateAccess#copyBufferSubData - 将一个缓冲区对象的数据存储的全部或部分复制到另一个缓冲区对象的数据存储。
  • com.mojang.blaze3d.pipeline.BlendFunction#INVERT - 反转 RGB 源和目标的混合因子。Alpha 使用源的默认因子,目标使用零。
  • com.mojang.blaze3d.systems.CommandEncoder#copyToBuffer - 将一个缓冲区切片的数据存储复制到另一个缓冲区切片。
  • net.minecraft.Util#isAarch64 - 返回操作系统架构是否使用 aarch64。
  • net.minecraft.client.gui.GuiGraphics#textHighlight - 在提供的边界周围添加一个高亮框。
  • net.minecraft.client.renderer.RenderPipelines#GUI_INVERT - 用于绘制具有反色效果的 GUI 元素的渲染管线。
  • net.minecraft.client.renderer.item.TrackingItemRenderState - 一个跟踪用于渲染物品堆栈的模型源的渲染状态。

变更列表

  • com.mojang.blaze3d.pipeline.RenderPipeline$Builder#withColorLogic 现已弃用
  • net.minecraft.client.gui.renderer.GuiRenderer#MIN_GUI_Z 现在是私有的
  • net.minecraft.client.gui.render.state.GuiItemRenderState 现在接受 TrackingItemRenderState 而不是 ItemStackRenderState
    • itemStackRenderState 现在返回 TrackingItemRenderState
  • net.minecraft.client.renderer.RenderPipelines#GUI_TEXT_HIGHLIGHT 现在使用 ADDITIVE 混合函数而不是 OR_REVERSE 颜色逻辑
  • net.minecraft.client.renderer.item.ItemStackRenderState#getModelIdentity -> TrackingItemRenderState#getModelIdentity

移除列表

  • net.minecraft.client.renderer.item.ItemStackRenderState#clearModelIdentity

Minecraft 1.21.7 -> 1.21.8 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

小幅迁移

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

新增列表

  • com.mojang.blaze3d.GraphicsWorkarounds - 一个用于解决特定图形硬件问题的辅助工具。

Minecraft 1.21.8 -> 1.21.9 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

感谢:

  • @Soaryn 指出了一些不推荐的渲染用法
  • @Deximus-Maximus 修正了一些拼写错误

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

调试大修

整个调试系统已被彻底改造,从暴露内部调试工具到调试屏幕。本文档旨在为处理您自己的调试屏幕和渲染器添加提供一个高层次概述。

调试渲染器

原版现在允许用户通过 JVM 属性启用 -DMC_DEBUG_ENABLED 以及其他所需标志来查看内部 API 提供的调试渲染器。用户可以利用这些暴露的功能,通过原版提供的管道来处理自己的渲染器。本概述将通过修补现有渲染器和订阅者(根据需要)进行说明,但这些通常可以在任何需要的地方设置。原版提供的好处是将其集成到现有对象(例如,实体、方块实体)以及跨网络的通用同步中。当然,您始终可以使用简单的 boolean 代替。毕竟,尽管 SharedConstants 中的标志是 final 的,但它们仍然每刻都会被检查。

订阅调试器

在大多数情况下,您想要渲染和调试的信息存储在服务器端。有时,相关信息会在客户端同步,但大多数情况下,它通常是某种仅用于渲染的部分状态。

// 服务器上的示例对象
public record ExampleObject(Block held, int count) {}

// 客户端上的示例
// Count 不用于渲染,仅用于服务器逻辑
public class ExampleRenderState {
    Block held;
}

因此,如果我们想查看来自服务器的额外数据,我们需要一种方法不仅能将其同步到客户端,还能在值发生变化时更新它。为此,原版提供了 DebugSubscription:一个类,用于存储同步对象所需的信息(如果它已更改)。构造函数包含两个字段:用于跨网络同步对象的 StreamCodec,以及一个可选的 int,当大于零时,如果在指定时间内没有更多更新,将从客户端清除同步的值。

为了处理与同步相关的逻辑,服务器使用 TrackingDebugSynchronizer 来处理玩家监听器并在必要时同步对象,并使用 LevelDebugSynchronizers 来处理同步器的通用跟踪和Tick。然后,这些数据被发送到 ClientDebugSubscriber 进行存储,并发送到 DebugRenderer 进行渲染。请注意,客户端只有在他们是单机世界的拥有者或服务器管理员时才能看到调试信息。此外,客户端只能请求添加到 ClientDebugSubscriber#requestedSubscriptions 提供的集合中的订阅。

DebugSubscription 必须注册到 BuiltInRegistries#DEBUG_SUBSCRIPTION

public static final DebugSubscription<ExampleObject> EXAMPLE_OBJECt = Registry.register(
    BuiltInRegistries.DEBUG_SUBSCRIPTION
    ResourceLocation.withNamespaceAndPath("examplemod", "example_object"),
    new DebugSubscription<>(
        // 用于同步示例对象的流编解码器
        StreamCodec.composite(
            ByteBufCodecs.registry(Registries.BLOCK), ExampleObject::block,
            ByteBufCodecs.VAR_INT, ExampleObject::count,
            ExampleObject::new
        ),
        // 更新之间的最大刻数
        //   在此之后数据将从客户端清除
        // 如果永不过期则设置为零
        0
    )
);

为了能够正确检查更新,所使用的对象必须正确实现 hashCodeequals,而不是依赖对象标识。

调试源

那么,我们如何告诉同步器跟踪和更新我们的 DebugSubscription?您可以扩展 TrackingDebugSynchronizer 或其子类,并通过修补 LevelDebugSynchronizers 或创建自己的类来实现跟踪和同步逻辑。但是,如果您要跟踪的数据直接附加到 LevelChunkEntityBlockEntity,并且可以从其关联的服务器对象更新,则可以使用 DebugValueSource

DebugValueSource 是一种将 DebugSubscription 注册为 TrackingDebugSynchronizer$SourceSynchronizer 的方法。这将每刻轮询并向每个启用订阅的跟踪源玩家发送更新。注册 DebugSubscription 通过 DebugValueSource#registerDebugValues 完成,它接受服务器等级和 $Registration 接口。然后通过 $Registration#register 传入订阅和构造订阅值的供应商来处理注册。

// 假设我们在下面的类中有某个 ExampleObject exampleObject

// 对于某个 BlockEntity、Entity 或 LevelChunk 子类
@Override
public void registerDebugValues(ServerLevel level, DebugValueSource.Registration registrar) {
    super.registerDebugValues(level, registrar);
    // 注册我们的订阅
    registrar.register(
        // 订阅
        EXAMPLE_OBJECT,
        // 提供的订阅对象
        () -> this.exampleObject
    );
}

渲染调试信息

一旦信息同步到客户端并存储在 ClientDebugSubscriber 中(假设您使用上述方法),我们现在需要将该信息渲染到屏幕上。这通常通过 DebugRenderer#render 处理,它在运行关联的渲染器之前通过 refreshRendererList 检查启用的调试渲染器。从技术上讲,数据在渲染过程中的任何点都可以获得,所以位置并不特别重要,但本文将假设您修补 refreshRendererList 以将您自己的渲染器添加到不透明或半透明渲染器中。

所有渲染器都实现 DebugRenderer$SimpleDebugRenderer 来调用 render,它提供当前的 PoseStack、缓冲区源、相机 XYZ 和 Frustum。此外,原版通过 Connection#createDebugValueAccess 传入一个 DebugValueAccess,以从 ClientDebugSubscriber 获取同步的调试信息。DebugRenderer 提供了使用 render* 在特定位置渲染文本或框的简单方法。

DebugValueAccess 包含两种类型的方法:get*Value 用于获取特定源(例如,位置、实体)的调试对象;以及 forEach*,用于遍历所有发送调试对象的源。您使用哪个取决于您将 DebugSubscription 注册到哪个源。

// 我们将假设我们的示例对象已注册到一个实体
public class ExampleObjectRenderer implements DebugRenderer.SimpleDebugRenderer {

    @Override
    public void render(PoseStack poseStack, MultiBufferSource bufferSource, double x, double y, double z, DebugValueAccess access, Frustum frustum) {
        // 遍历所有带有我们示例对象的块
        access.forEachEntity(EXAMPLE_OBJECT, (entity, exampleObject) -> {
            // 渲染调试信息
            DebugRenderer.renderTextOverMob(
                poseStack, bufferSource, entity,
                // 文本 Y 偏移(实体显示很多信息)
                100,
                // 要渲染的文本
                "持有计数: " + exampleObject.count(),
                // 文本颜色
                0xFFFFFFFF,
                // 文本缩放
                1f
            );
        });
    }
}

调试屏幕

调试屏幕允许用户启用、禁用或仅在 F3 中显示特定组件。这个模块化系统允许模组制作者将自己的调试条目添加到屏幕中。并非本文说明的所有部分都可以在没有更多模组工作的情况下访问,因此这些区域将被特别指出。

DebugScreenEntry

每个调试选项都有自己的条目,要么定义显示的内容(例如,fps、内存),要么是无操作,由单独的实现处理(例如,实体碰撞箱、区块边界)。这被称为 DebugScreenEntry,它定义了三个方法。

首先是 category。在原版中,这几乎总是 DebugEntryCategory#SCREEN_TEXT,因为所有调试条目所做的就是在屏幕上绘制文本。另一个可用选项 RENDERER 仅用于无操作,因为渲染选项总是独立于调试屏幕渲染。DebugEntryCategory 只是一个带有标签和某种排序键值的记录,因此可以通过调用构造函数添加更多。该类别仅用于在调试选项屏幕中搜索。

接下来是 isAllowed。此方法决定调试选项是否应独立于条目状态在屏幕上渲染。默认情况下,仅当 Minecraft#showOnlyReducedInfo 辅助功能选项为 false 时才为 true。一些调试条目覆盖此方法以始终返回 true,或者如果某个其他检查通过。

最后是 display 方法。它负责使用 DebugScreenDisplayer 将文本绘制到屏幕。它还接受当前的 Level、客户端区块和服务器区块。DebugScreenDisplayer 有四个方法,每个方法都将文本绘制到屏幕。首先,有标准的 addLine 方法,它只是将字符串添加到左侧或右侧,具体取决于其渲染的元素。这些将一个接一个地出现。然后,有 addPriorityLine,它将始终添加到左侧或右侧的顶部。最后,有 addToGroup,它接受一个额外的键,将行渲染为一个单独的组,并在末尾添加一个额外的换行符。

public class ExampleDebugEntry implements DebugScreenEntry {

    public static final ResourceLocation GROUP_ONE = ResourceLocation.fromNamespaceAndPath("examplemod", "group_one");
    public static final ResourceLocation GROUP_TWO = ResourceLocation.fromNamespaceAndPath("examplemod", "group_two");


    @Override
    public void display(DebugScreenDisplayer displayer, @Nullable Level level, @Nullable LevelChunk clientChunk, @Nullable LevelChunk serverChunk) {
        // 如果它是屏幕上唯一的条目,以下将显示如下:
        // 左侧第一!                                                右侧第一!
        // 
        // 世界你好!                                                随机文本!
        // 洛雷姆·伊普苏姆。
        //                                                            我是另一个组!
        // 我是一个组                                                这将出现在没有换行符之后!
        // 全部排成一行
        // 以列表形式提供。
        //

        displayer.addLine("世界你好!");
        displayer.addLine("洛雷姆·伊普苏姆。");
        displayer.addLine("随机文本!");

        // 这些将首先显示
        displayer.addPriorityLine("左侧第一!");
        displayer.addPriorityLine("右侧第一!");

        // 这些将根据键单独分组
        displayer.addToGroup(GROUP_ONE, List.of(
            "我是一个组",
            "全部排成一行",
            "以列表形式提供。"
        ));

        displayer.addToGroup(GROUP_TWO, "我是另一个组!");
        displayer.addToGroup(GROUP_TWO, "这将出现在没有换行符之后!");
    }

    @Override
    public boolean isAllowed(boolean reducedDebugInfo) {
        // 无论辅助功能选项如何,始终显示
        return true;
    }
}

然后,只需将您的条目注册到 DebugScreenEntries 即可显示。可以通过调试菜单使用提供的键进行切换。

// 此方法是私有的,因此需要扩宽其访问权限
DebugScreenEntries.register(
    // id,这将显示在选项屏幕上
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_entry"),
    // 屏幕条目
    new ExampleScreenEntry();
);

外部切换和检查

如果您想从选项菜单单独切换活动状态怎么办?如果您想检查条目是否已启用以在游戏中显示调试数据怎么办?这可以通过 Minecraft 实例访问 DebugScreenEntryList 来完成。

切换当前状态可以通过 DebugScreenEntryList#toggleStatus 完成。其行为取决于当前活动的屏幕。基本上,调用 toggle 将始终翻转调试条目的开关:如果它当前不在屏幕上,它将在屏幕上渲染,反之亦然。如果在 F3 中,那么 toggle on 将仅在 F3 打开时渲染该调试条目。

然后可以使用 DebugScreenEntryList#isCurrentlyEnabled 检查条目的状态。这将仅检查调试屏幕是否在当前打开的列表中,而不检查 DebugScreenEntry#isAllowed

// 让我们创建另一个条目
public static final ResourceLocation EXAMPLE_TOGGLE = DebugScreenEntries.register(
    ResourceLocation.fromNamespaceAndPath("examplemod", "example_toggle"),
    // 我们使用无操作,因为没有文本显示
    new DebugEntryNoop();
);

// 切换:
Minecraft.getInstance().debugEntries.toggleStatus(EXAMPLE_TOGGLE);

// 检查是否启用:
if (Minecraft.getInstance().debugEntries.isCurrentlyEnabled(EXAMPLE_TOGGLE)) {
    // ...
}

配置文件

配置文件是根据用户意愿配置的预定义预设。目前,配置文件被硬编码为默认或性能。要扩展系统,您需要能够动态地向 DebugScreenProfile 枚举添加条目,使 DebugScreenEntries#PROFILES 映射可变以添加您的配置文件和预设,并使用您的配置文件按钮修改调试选项屏幕。

  • net.minecraft.SharedConstants
    • DEBUG_SHUFFLE_MODELS - 一个可能打乱模型加载顺序的标志。
    • DEBUG_FLAG_PREFIX - 放在每个调试标志前面的前缀。
    • USE_DEBUG_FEATURES -> DEBUG_ENABLED
    • DEBUG_RENDER 已移除
    • DEBUG_WORLDGENATTEMPT 已移除
    • debugGenerateStripedTerrainWithoutNoise 已移除
    • DEBUG_RESOURCE_GENERATION_OVERRIDE 已移除
    • DEBUG_POI - 启用 POI 调试渲染器。
    • DEBUG_PANORAMA_SCREENSHOT - 启用时,允许用户拍摄全景截图。
    • DEBUG_CHASE_COMMAND - 启用时,添加 chase 命令。
    • FAKE_MS_LATENCY -> DEBUG_FAKE_LATENCY_MS
    • FAKE_MS_JITTER -> DEBUG_FAKE_JITTER_MS
    • DEBUG_VERBOSE_COMMAND_ERRORS - 启用时,通过聊天框输出详细错误。
    • DEBUG_DEV_COMMANDS - 启用时,添加用于调试游戏的命令。
  • net.minecraft.client.Minecraft
    • debugEntries - 返回一个调试功能列表以及应在屏幕上显示的内容。
    • fpsStringsectionPathsectionVisibility 已移除
    • debugRenderer -> LevelRenderer#debugRenderer
  • net.minecraft.client.gui.Gui
    • renderDebugOverlay 现在是公开的
    • shouldRenderDebugCrosshair 已移除
  • net.minecraft.client.gui.components.DebugScreenOverlay
    • drawGameInformationdrawSystemInformation 已移除
    • getGameInformationgetSystemInformation 已移除
    • toggleOverlay 已移除
  • net.minecraft.client.gui.components.debug
    • DebugEntryBiome - 一个显示相机实体所在生物群系的调试条目。
    • DebugEntryCategory - 一个描述调试条目如何显示的类别。
    • DebugEntryChunkGeneration - 一个显示当前区块生成信息的调试条目。
    • DebugEntryChunkRenderStats - 一个显示当前区块统计信息的调试条目。
    • DebugEntryChunkSourceStats - 一个显示区块源通用元数据的调试条目。
    • DebugEntryEntityRenderStats - 一个显示实体存储通用元数据的调试条目。
    • DebugEntryFps - 一个显示每秒帧数和垂直同步信息的调试条目。
    • DebugEntryGpuUtilization - 一个显示 GPU 利用率的调试条目。
    • DebugEntryHeightmap - 一个显示当前位置高度图的调试条目。
    • DebugEntryLight - 一个显示客户端光照信息的调试条目。
    • DebugEntryLocalDifficulty - 一个显示当前世界难度和时间的调试条目。
    • DebugEntryLookingAtBlock - 一个显示相机当前正在查看的方块的调试条目。
    • DebugEntryLookingAtEntity - 一个显示相机当前正在查看的实体的调试条目。
    • DebugEntryLookingAtFluid - 一个显示相机当前正在查看的流体的调试条目。
    • DebugEntryMemory - 一个显示游戏分配和使用的内存的调试条目。
    • DebugEntryNoop - 一个不显示任何内容的调试条目。
    • DebugEntryParticleRenderState - 一个显示正在渲染的粒子数量的调试条目。
    • DebugEntryPosition - 一个显示相机实体的当前位置和旋转的调试条目。
    • DebugEntryPostEffect - 一个显示当前应用的后处理效果的调试条目。
    • DebugEntrySectionPosition - 一个显示当前部分位置的调试条目。
    • DebugEntrySimplePerformanceImpactors - 一个显示图形模式、云状态和生物群系混合半径的调试条目。
    • DebugEntrySoundMood - 一个显示当前播放的声音和玩家情绪的调试条目。
    • DebugEntrySpawnCounts - 一个显示每个生物类别的实体生成数量的调试条目。
    • DebugEntrySystemSpecs - 一个显示运行机器规格的调试条目。
    • DebugEntryTps - 一个显示通用每秒刻数的调试条目。
    • DebugEntryVersion - 一个显示当前 Minecraft 版本的调试条目。
    • DebugScreenDisplayer - 一个接口,调试条目使用它来将元素显示到屏幕。
    • DebugScreenEntries - Minecraft 注册的调试条目。
    • DebugScreenEntry - 一个元素,如果启用,则在调试覆盖层启用时显示。
    • DebugScreenEntryList - 有关在屏幕上显示哪些调试元素的选项信息。
    • DebugScreenEntryStatus - 调试条目应显示的状态。
    • DebugScreenProfile - 一个枚举,表示调试屏幕在决定显示哪些条目时可以设置的配置文件。
  • net.minecraft.client.gui.screen.debug.DebugOptionsScreen - 一个允许用户更改配置文件的显示调试条目的屏幕。
  • net.minecraft.client.renderer.LevelRenderer
    • getSectionStatistics 现在可为 null
    • getEntityStatistics 现在可为 null
    • gameTestBlockHighlightRenderer - 游戏测试中方块高亮的渲染器。
  • net.minecraft.client.renderer.debug.DebugRenderer
    • switchRenderChunkborder -> DebugScreenEntries#CHUNK_BORDERS,不是一对一
    • toggleRenderOctree -> DebugScreenEntries#CHUNK_SECTION_OCTREE,不是一对一
  • net.minecraft.client.multiplayer
    • DebugSampleSubscriber -> ClientDebugSubscriber,不是一对一
    • ClientPacketListener#createDebugValueAccess - 创建用于获取当前调试值的访问器。
  • net.minecraft.client.renderer.debug
    • BeeDebugRenderer#addOrUpdateHiveInfoaddOrUpdateBeeInforemoveBeeInfo 已移除
    • BrainDebugRenderer
      • addPoiremovePoi$PoiInfo 已移除
      • setFreeTicketCount 已移除
      • addOrUpdateBrainDumpremoveBrainDump 已移除
    • BreezeDebugRenderer 现在实现 DebugRenderer$SimpleDebugRenderer
      • render 现在接受一个 DebugValueAccess
      • clearadd 已移除
    • DebugRenderer 不再接受 Minecraft 实例
      • 所有字段渲染器已从公共访问中移除,而是存储在某个 *Renderers 列表中
      • worldGenAttemptRenderer 已移除
      • renderTextOverBlock - 在提供的方块位置上方渲染给定的流。
      • renderTextOverMob - 在提供的实体上方渲染给定的字符串。
      • refreshRendererList - 使用启用的调试渲染器填充渲染器列表。
      • renderrenderAfterTranslucents 已合并到 render 中,其中 boolean 决定是渲染半透明还是不透明的渲染器
      • $SimpleDebugRenderer
        • render 现在接受一个 DebugValueAccessFrustum
        • clear 已移除
    • EntityBlockIntersectionDebugRenderer - 一个用于显示实体相交的方块的调试渲染器。
    • GameEventListenerRenderer 不再接受 Minecraft 实例
      • trackGameEventtrackListener 已移除
    • GameTestDebugRenderer -> GameTestBlockHighlightRenderer,不是一对一
      • addMarker -> highlightPos,不是一对一
    • GoalSelectorDebugRenderer#addGoalSelectorremoveGoalSelector 已移除
    • NeighborsUpdateRenderer 不再接受 Minecraft 实例
      • addUpdate 已移除
    • OctreeDebugRenderer 现在实现 DebugRenderer$SimpleDebugRenderer
    • PathfindingRenderer#addPath 已移除
    • PoiDebugRenderer - 一个用于显示兴趣点的调试渲染器。
    • RaidDebugRenderer#setRaidCenters 已移除
    • RedstoneWireOrientationsRenderer 不再接受 Minecraft 实例
      • addWireOrientation 已移除
    • StructureRenderer 不再接受 Minecraft 实例
      • addBoundingBox 已移除
    • VillagerSectionsDebugRenderer#setVillageSectionsetNotVillageSection 已移除
    • WorldGenAttemptRenderer 类已移除
  • net.minecraft.core.registries.BuiltInRegistriesRegistries#DEBUG_SUBSCRIPTION - 调试处理程序订阅的注册表。
  • net.minecraft.gametest.framework
    • GameTestAssertPosException#getMessageToShowAtBlock 现在返回一个 Component
    • GameTestRunner#clearMarkers 已移除
  • net.minecraft.network.protocol.common.custom
    • 所有类已移至 net.minecraft.util.debug
    • 它们不再是有效负载,而是仅包含对象信息和关联流编解码器的记录
    • 如果有效负载类有一个关联的内部对象类,则该类被移动,有效负载类被移除
    • 否则,有效负载类被添加,没有 *Payload 后缀,大多数情况下带有 *Info 后缀
  • net.minecraft.network.protocol.game
    • ClientboundDebugBlockValuePacket - 发送到客户端的数据包,关于方块位置上的调试值更改。
    • ClientboundDebugChunkValuePacket - 发送到客户端的数据包,关于区块位置上的调试值更改。
    • ClientboundDebugEntityValuePacket - 发送到客户端的数据包,关于实体上的调试值更改。
    • ClientboundDebugEventPacket - 发送到客户端的数据包,关于触发的调试事件。
    • ClientboundGameTestHighlightPosPacket - 发送到客户端的数据包,关于要高亮的游戏测试位置。
    • ClientGamePacketListener
      • handleDebugChunkValue - 处理调试区块位置数据包。
      • handleDebugBlockValue - 处理调试方块位置数据包。
      • handleDebugEntityValue - 处理调试实体数据包。
      • handleDebugEvent - 处理触发的调试事件。
      • handleGameTestHighlightPos - 处理提供的高亮位置。
    • DebugPackets 类已移除
    • ServerboundDebugSampleSubscriptionPacket -> ServerboundDebugSubscriptionRequestPacket,不是一对一
    • ServerGamePacketListener#handleDebugSampleSubscription -> handleDebugSubscriptionRequest,不是一对一
  • net.minecraft.server.MinecraftServer
    • subscribeToDebugSample 已移除
    • debugSubscribers - 返回已跟踪订阅到已启用它的玩家列表的映射。
  • net.minecraft.server.level
    • ChunkMap
      • isChunkTracked 现在是公开的
      • getChunks 已移除
    • ServerLevel#debugSynchronizers - 返回等级的调试器处理程序和同步器。
    • ServerPlayer
      • requestDebugSubscriptions - 设置玩家正在监听的调试器。
      • debugSubscriptions - 返回玩家正在监听的调试器。
  • net.minecraft.util.debug
    • DebugSubscription - 一个可以监听或订阅的跟踪数据点。
    • DebugSubscriptions - 原版调试订阅。
    • DebugValueAccess - 访问调试订阅跟踪的值,在客户端上用于调试渲染器。
    • DebugValueSource - 定义一个提供要跟踪的调试值的源对象,例如一个实体。
    • LevelDebugSynchronizers - 处理将订阅数据通过网络发送到跟踪客户端。
    • ServerDebugSubscribers - 处理订阅了当前启用订阅的玩家的全局状态。
    • TrackingDebugSynchronizer - 处理订阅了某个订阅的玩家列表。
  • net.minecraft.util.debugchart
    • DebugSampleSubscriptionTracker 类已移除
    • RemoteDebugSampleType 现在接受一个 DebugSubscription
      • subscription - 返回样本类型报告的订阅。
    • RemoteSampleLogger 现在接受 ServerDebugSubscribers 而不是 DebugSampleSubscriptionTracker
  • net.minecraft.world.entity
    • Entity 现在实现 DebugValueSource
    • Mob#sendDebugPackets 已移除
  • net.minecraft.world.entity.ai.village.poi
    • PoiManager#getFreeTickets -> getDebugPoiInfo,不是一对一
    • PoiSection#getDebugPoiInfo - 返回给定位置的调试 POI 信息。
  • net.minecraft.world.level.block.entity
    • BlockEntity 现在实现 DebugValueSource
    • TestInstanceBlockEntity#markErrorclearErrorMarkersgetErrorMarkers$ErrorMarker - 处理测试实例设置的错误标记。
  • net.minecraft.world.level.chunk.LevelChunk 现在实现 DebugValueSource
  • net.minecraft.world.level.pathfinder.PathFinder#setCaptureDebug - 设置是否应捕获路径以进行调试。
  • net.minecraft.world.level.redstone.CollectingNeighborUpdater#setDebugListener - 设置用于调试的方块位置更改的监听器。

功能提交:电影版

整个渲染管线,从实体到方块实体再到粒子,已被重做为称为“功能”的提交/渲染阶段系统。本指南将介绍功能系统的基础知识,然后介绍如何使用它实现每种主要类型。

提交与渲染

功能系统,就像 GUI 一样,分为两个阶段:提交和渲染。提交阶段由 SubmitNodeCollector 处理,它基本上收集将对象抽象渲染到屏幕所需的数据。这一切都是通过 submit* 方法完成的,这些方法通常接受一个 PoseStack 来将对象放置在 3D 空间中,以及任何其他所需的数据,如模型、状态、渲染类型等。

以下是每个方法接受的参数的快速概述:

方法参数
submitHitbox一个姿势堆栈、实体的渲染状态和碰撞箱渲染状态
submitShadow一个姿势堆栈、阴影半径和阴影碎片
submitNameTag一个姿势堆栈、一个可选位置、Y 偏移、文本组件、文本是否应透明(如潜行时)、光照坐标和相机渲染状态
submitText一个姿势堆栈、XY 偏移、文本序列、是否添加阴影、字体显示模式、光照坐标、颜色、背景颜色和轮廓颜色
submitFlame一个姿势堆栈、实体的渲染状态和一个旋转四元数
submitLeash一个姿势堆栈和拴绳状态
submitModel一个姿势堆栈、实体模型、渲染状态、渲染类型、光照坐标、覆盖坐标、色调颜色、一个可选纹理、轮廓颜色和一个可选的破碎覆盖
submitModelPart一个姿势堆栈、模型部件、渲染类型、光照坐标、覆盖坐标、一个可选纹理、如果渲染类型不透明则是否对物品使用闪光而非实体闪光、是否渲染闪光覆盖、色调颜色、一个可选的破碎覆盖和轮廓颜色
submitBlock一个姿势堆栈、方块状态、光照坐标、覆盖坐标和轮廓颜色
submitMovingBlock一个姿势堆栈和移动方块的渲染状态
submitBlockModel一个姿势堆栈、渲染类型、方块状态模型、RGB 浮点数、光照坐标、覆盖坐标和轮廓颜色
submitItem一个姿势堆栈、物品显示上下文、光照坐标、覆盖坐标、轮廓颜色、色调层、四边形、渲染类型和闪光类型
submitCustomGeometry一个姿势堆栈、渲染类型和一个接受当前姿势和 VertexConsumer 以创建网格的函数
submitParticleGroup一个 SubmitNodeCollector$ParticleGroupRenderer

从技术上讲,submit* 方法由 OrderedSubmitNodeCollector 提供,SubmitNodeCollector 扩展了它。这是因为功能可以提交到不同的顺序,其功能类似于 GUI 中的层(strata)。默认情况下,所有提交调用都被推送到顺序 0。使用 SubmitNodeCollector#order 加上某个整数,然后调用 submit* 方法,您可以让一个对象在给定顺序上的所有功能之前或之后渲染。这存储为一个 AVL 树,其中每个顺序的数据存储在一个 SubmitNodeCollection 中。使用当前的默认功能渲染顺序,这仅在非常特定的情况下使用,例如渲染史莱姆的外层身体或装备层。

// 假设我们可以访问 `SubmitNodeCollector` collector

// 这将在顺序 0 中渲染
collector.submitModel(...);

// 这将在 `submitModel` 调用之前渲染
collector.order(-1).submitShadow(...);

// 这将在 `submitModel` 调用之后渲染
collector.order(1).submitNameTag(...);

渲染阶段由 FeatureRenderDispatcher 处理,它使用其提交的功能渲染器渲染对象。什么是功能渲染器?实际上就是一个任意方法,它遍历它将推送到缓冲区的节点内容。目前,对于给定的顺序,功能按如下方式推送其顶点:阴影、模型、模型部件、火焰动画、实体名称标签、任意文本、碰撞箱、拴绳、物品、方块、自定义渲染管线,最后是粒子。每个顺序,从最小数字到最大数字,将重新运行所有功能渲染,直到到达树的末尾。然后所有提交将被清除以供下次使用。

大多数功能分派器只是对其集合运行一个循环。那些存储渲染类型的会将渲染调用批处理到一个缓冲区。同时,ModelFeatureRenderer 更进一步,将其半透明模型按距离相机的距离排序,并在所有不透明模型之后将它们发送到缓冲区。

实体模型

那么,这如何影响实体?让我们从构成所有实体模型的根 Model 开始。Model 现在有一个泛型,用于将支持对象的状态传递给 setupAnim,该方法也已移至 Model。这意味着基本模型类很少被传递,而是选择某个子类型,例如用于告示牌的 Model$Simple。鉴于大多数 EntityModel 已经需要 EntityRenderState 的泛型,这不会影响任何东西。

主要变化来自模型部件可见性的工作方式,例如盔甲和披风。每一个单独的部件(例如,头盔、胸甲)现在都有自己独立的模型,这意味着通用的部件可见性系统已被完全移除。您仍然可以在 setupAnim 中通过可变的模型部件提供可见性,但通常的做法是简单地将应该分开的模型部件作为单独的模型。

为了促进这一点,PartDefinition 现在有一些方法可以选择性地保留模型的某些部分并移除其他部分。这是通过 clear*retain* 方法完成的。基本上,所有这些方法所做的就是保留部件姿势,同时移除与子查询关联的任何立方体。retain* 允许某些部分和可能的子部分保留它们的立方体。这一增加提供了双重好处:模型层可以确定性地使用 setupAnim 以与基础模型类似的方式设置部件,并且模型纹理将只需要包含保留的元素。

以下是为苦力怕创建盔甲模型的示例:

// 人形盔甲的变形
private static final CubeDeformation OUTER_ARMOR_DEFORMATION = new CubeDeformation(1.0F);
private static final CubeDeformation INNER_ARMOR_DEFORMATION = new CubeDeformation(0.5F);

// 苦力怕有以下部分:
// - head
// - body
// - right_hind_leg, left_hind_leg
// - right_front_leg, left_front_leg

// 我们使用单独的网格,因为我们基本上要隔离我们想要保留在每一个中的部分

public static ArmorModelSet<MeshDefinition> createCreeperArmor() {
    // 头盔

    // 创建网格
    MeshDefinition helmetMesh = CreeperModel.createBodyLayer(OUTER_ARMOR_DEFORMATION);
    // 仅保留所需部分
    // 注意 body 和腿仍然存在,它们只是没有立方体
    helmetMesh.getRoot().retainExactParts(Set.of("head"));

    // 胸甲

    // 创建网格
    var chestplateMesh = CreeperModel.createBodyLayer(OUTER_ARMOR_DEFORMATION);
    // 仅保留所需部分
    chestplateMesh.getRoot().retainExactParts(Set.of("body"));

    // 护腿

    // 创建网格
    var leggingsMesh = CreeperModel.createBodyLayer(INNER_ARMOR_DEFORMATION);
    // 仅保留所需部分
    leggingsMesh.getRoot().retainExactParts(Set.of("right_hind_leg", "left_hind_leg", "right_front_leg", "left_front_leg"));

    // 靴子

    // 创建网格
    var bootsMesh = CreeperModel.createBodyLayer(OUTER_ARMOR_DEFORMATION);
    // 仅保留所需部分
    bootsMesh.getRoot().retainExactParts(Set.of("right_hind_leg", "left_hind_leg", "right_front_leg", "left_front_leg"));

    // 将所有内容存储在 ArmorModelSet 中,基本上只是一个对象持有者和映射器
    return new ArmorModelSet<>(
        helmetMesh,
        chestplateMesh,
        leggingsMesh,
        bootsMesh
    );
}

// 要注册层定义,基本上使用 ArmorModelSet 的相同过程
public static final ArmorModelSet<ModelLayerLocation> CREEPER_ARMOR = new ArmorModelSet<>(
    new ModelLayerLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "creeper"), "helmet"),
    new ModelLayerLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "creeper"), "chestplate"),
    new ModelLayerLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "creeper"), "leggings"),
    new ModelLayerLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "creeper"), "boots")
);

// 在某个可以访问 Map<ModelLayerLocation, LayerDefinition> builder 的方法中
ArmorModelSet<LayerDefinition> creeperArmorLayers = createCreeperArmor().map(mesh -> LayerDefinition.create(mesh, 64, 32));
CREEPER_ARMOR.putFrom(creeperArmorLayers, builder);

实体渲染器

随着提交的更改,EntityRenderer 及其关联的 RenderLayer 也发生了变化。基本上,您可以假设几乎所有带有 render 一词的方法都已更改为 submit,并且 MultiBufferSource 和光照坐标整数通常已被 SubmitNodeCollector 和关联的实体渲染状态取代。

EntityRenderer 中替换 render 的新 submit 方法现在接受实体的渲染状态、PoseStackSubmitNodeCollectorCameraRenderState。提交任何元素时,3D 空间中的位置通过获取 PoseStack 上的最后一个姿势并将其存储以供将来使用。

// 一个基本的实体渲染器

// 我们将假设所有列出的类都存在
public class ExampleEntityRenderer extends MobRenderer<ExampleEntity, ExampleEntityRenderState, ExampleModel> {

    public ExampleEntityRenderer(EntityRendererProvider.Context ctx) {
        super(ctx, ctx.bakeLayer(EXAMPLE_MODEL_LAYER), 0.5f);
    }

    @Override
    public void submit(ExampleEntityRenderState renderState, PoseStack poseStack, SubmitNodeCollector collector, CameraRenderState cameraState) {
        super.submit(renderState, poseStack, collector, cameraState);

        // 提交某些内容的示例
        collector.submitCustomGeometry(
            poseStack, // 当前姿势
            RenderType.solid(), // 要使用的渲染类型
            ExampleEntityRenderer::addVertices // 写入几何数据的方法
        );
    }

    private static void addVertices(PoseStack.Pose pose, VertexConsumer consumer) {
        // 添加自定义几何体
    }
}

// 一个渲染层

public class CreeperArmorLayer extends RenderLayer<CreeperRenderState, CreeperModel> {

    private final ArmorModelSet<CreeperModel> modelSet;
    private final EquipmentLayerRenderer equipment;

    public CreeperArmorLayer(RenderLayerParent<CreeperRenderState, CreeperModel> parent, ArmorModelSet<CreeperModel> modelSet, EquipmentLayerRenderer equipment) {
        super(parent);
        this.modelSet = modelSet;
        this.equipment = equipment;
    }

    // 我们将假设我们以某种方式向 CreeperRenderState 添加了 headEquipment、chestEquipment、legsEquipment、feetEquipment
    @Override
    public void submit(PoseStack poseStack, SubmitNodeCollector collector, int lightCoords, CreeperRenderState renderState, float yRot, float xRot) {
        this.renderArmorPiece(poseStack, collector, renderState.chestEquipment, EquipmentSlot.CHEST, lightCoords, renderState);
        this.renderArmorPiece(poseStack, collector, renderState.legsEquipment,  EquipmentSlot.LEGS,  lightCoords, renderState);
        this.renderArmorPiece(poseStack, collector, renderState.feetEquipment,  EquipmentSlot.FEET,  lightCoords, renderState);
        this.renderArmorPiece(poseStack, collector, renderState.headEquipment,  EquipmentSlot.HEAD,  lightCoords, renderState);
    }

    // 取自人形盔甲层
    private void renderArmorPiece(PoseStack poseStack, SubmitNodeCollector collector, ItemStack stack, EquipmentSlot slot, int lightCoords, CreeperRenderState renderState) {
        Equippable equippable = stack.get(DataComponents.EQUIPPABLE);
        if (equippable != null && equippable.assetId().isPresent() && equippable.slot() == slot) {
            CreeperModel model = this.modelSet.get(slot);
            EquipmentClientInfo.LayerType layer = slot == EquipmentSlot.LEGS
                ? EquipmentClientInfo.LayerType.HUMANOID_LEGGINGS
                : EquipmentClientInfo.LayerType.HUMANOID;
            this.equipmentRenderer.renderLayers(
                layer, // 要使用的装备层
                equippable.assetId().orElseThrow(), // 要拉取的装备资源
                model, // 盔甲模型
                renderState, // 实体渲染状态
                stack, // 盔甲堆栈
                poseStack, // 姿势堆栈
                collector, // 用于添加模型数据的收集器
                lightCoords, // 光照坐标
                renderState.outlineColor // 实体的轮廓颜色
            );
        }
    }
}

// 然后,将其添加到苦力怕渲染器的构造函数中
public CreeperRenderer(EntityRendererProvider.Context ctx) {
    // ...
    this.addLayer(new CreeperArmorLayer(
        this, // 父级是渲染器本身
        ArmorModelSet.bake( // 烘焙模型集
            CREEPER_ARMOR, // 模型层位置
            ctx.getModelSet(), // 用于从层位置映射模型的模型集
            CreeperModel::new // 根部件到模型的映射器
        ),
        ctx.getEquipmentRenderer() // 装备的渲染器
    ));
}

方块实体渲染器

BlockEntityRenderer 也使用新的提交方法,几乎将所有 render* 替换为 submit。它们借鉴了实体的做法,现在有自己的 BlockEntityRenderState,从 BlockEntity 中提取。因此,BlockEntityRenderer 现在有一个新的泛型 S,表示 BlockEntityRenderState

默认情况下,BlockEntityRenderState 包含关于其位置、方块状态、类型、光照坐标以及作为 ModelFeatureRenderer$CrumblingOverlay 的当前破坏进度的信息。这些信息都通过 BlockEntityRenderState#extractBase 填充,该方法在 BlockEntityRenderer#extractRenderState 中调用。与实体一样,渲染状态首先通过 BlockEntityRenderer#createRenderState 构造,然后从方块实体中提取值。extractRenderState 确实包含部分刻和相机位置,但默认情况下不会传递给 BlockEntityRenderState

因此,接管 render 方法的 submit 方法接受渲染状态、用于 3D 空间位置的 PoseStack、用于推送要渲染的元素的 SubmitNodeCollector 以及 CameraRenderState

// 我们将假设所有未在此处指定的类都存在

// 一个简单的渲染状态
public class ExampleRenderState extends BlockEntityRenderState {
    public float partialTick;
}

// 一个基本的方块实体渲染器
public class ExampleBlockEntityRenderer implements BlockEntityRenderer<ExampleBlockEntity, ExampleRenderState> {

    public ExampleBlockEntityRenderer(BlockEntityRendererProvider.Context ctx) {
        // 从上下文中获取任何需要的内容
    }

    @Override
    public ExampleRenderState createRenderState() {
        // 创建用于将方块实体提交到功能渲染器的渲染状态
        return new ExampleRenderState();
    }

    @Override
    public void extractRenderState(ExampleBlockEntity blockEntity, ExampleRenderState renderState, float partialTick, Vec3 cameraPos, @Nullable ModelFeatureRenderer.CrumblingOverlay crumblingOverlay) {
        // 从方块实体中提取必要的渲染值到渲染状态
        // 始终调用 super 或 BlockEntityRenderState#extractBase
        super.extractRenderState(blockEntity, renderState, partialTick, cameraPos, crumblingOverlay);

        // 填充任何所需的值
        renderState.partialTick = partialTick;
    }


    @Override
    public void submit(ExampleRenderState renderState, PoseStack poseStack, SubmitNodeCollector collector, CameraRenderState cameraState) {
        // 提交某些内容的示例
        collector.submitModel(..., renderState.breakProgress);
    }
}

特殊物品模型

由于特殊物品模型也使用自定义渲染,它们已更新为 submit 更改,仅将 MultiBufferSource 替换为 SubmitNodeCollector

// 一个基本的特殊物品模型

// 我们将假设所有列出的类都存在
public class ExampleSpecialModelRenderer implements NoDataSpecialModelRenderer {

    public ExampleSpecialModelRenderer() {}

    @Override
    public void submit(ItemDisplayContext displayContext, PoseStack poseStack, SubmitNodeCollector collector, int lightCoords, int overlayCoords, boolean hasFoil, int outlineColor) {
        // 提交某些内容的示例
        collector.submitModelPart(...);
    }

    @Override
    public void getExtents(Set<Vector3f> extents) {}
}

粒子

粒子已被添加到提交过程中;然而,根据粒子的复杂程度,有多条路径。一些类和通用名称也被重用于额外的目的,有时使理解每个部分的工作原理变得困难。因此,本文档将介绍两种创建粒子的方法:一种更熟悉旧系统,另一种从头开始解释底层细微差别。

引擎和资源的分离

在我们讨论这两种方法之前,首先,让我们了解总体变化。ParticleEngine 在功能上被拆分为两个类:ParticleEngine,负责处理实际的Tick和提取(而不是提交)渲染状态;以及 ParticleResources,它是注册 ParticleProvider 和可选的 ParticleResources$SpriteParticleRegistration 并从其 ParticleDescription 重新加载 SpriteSet 的重载监听器。这种底层行为没有改变(除了整个提取和提交过程),方法只是被移动了。

ParticleProvider#createParticle 现在也提供了一个 RandomSource,可以根据需要使用。

至于实际的提交和渲染过程,这由 ParticleEngine 之外处理。更具体地说,LevelRenderer 通过 ParticleEngine#extract 将所有粒子提取到 ParticlesRenderState 中。然后,在 LevelRenderer#addParticlesPass 中,资源句柄被设置到粒子的 FramePass,在执行时,粒子通过 ParticlesRenderState#submit 提交,然后通过 ParticleFeatureRenderer 通过功能分派器渲染。

单个四边形

旧系统中的许多粒子仅仅是由一个带有纹理的单个四边形组成。这些粒子是 SingleQuadParticle,它将之前的 SingleQuadParticleTextureSheetParticle 合并为一个。SingleQuadParticle 现在接受一个初始的 TextureAtlasSprite 来设置第一个纹理,然后可以通过覆盖 Particle#tick 并调用 SingleQuadParticle#setSpriteFromAge 来更新 SpriteSet,或者直接使用 setSprite 来更新。色调也可以在Tick中使用 setColorsetAlpha 修改。有些也在 SingleQuadParticle#extract 中直接设置,但使用哪个取决于您是否需要覆盖整个Tick。

要确定用于渲染四边形的 RenderType,必须将 SingleQuadParticle#getLayer 设置为所需的 $Layer$Layer 基本上是一个记录,定义四边形是否可以具有半透明、它从哪个纹理图集拉取以及要使用的渲染管线。原版提供了类似于旧 Particle#getRenderTypeTERRAINOPAQUETRANSLUCENT,它取代了这些。TERRAINTRANSLUCENT 都允许透明度,OPAQUETRANSLUCENT 从粒子图集拉取,而 TERRAIN 使用方块图集。可以使用构造函数创建自定义的 $Layer

public static final SingleQuadParticle.Layer EXAMPLE_LAYER = new SingleQuadParticle.Layer(true, TextureAtlas.LOCATION_PARTICLES, RenderPipelines.WEATHER_DEPTH_WRITE);

除此之外,您还可以通过覆盖 SingleQuadParticle#getFacingCameraMode 来设置粒子的旋转方式。$FacingCameraMode 是一个函数式接口,在提取粒子时设置粒子的旋转。默认情况下,这意味着纹理将始终面向相机。任何其他方法的更改和添加都在下面的列表中。

从那里开始,创建 ParticleProvider 并注册它的所有其他内容都是相同的。

// 我们将假设我们的粒子有某个 SimpleParticleType EXAMPLE_QUAD
// 此外,我们将假设有某个粒子描述,其中包含要使用的纹理
public class ExampleQuadParticle extends SingleQuadParticle {

    private final SpriteSet spriteSet;

    // 这可以是包私有、受保护或公开的
    // 如果粒子将在提供者之外构造,则应使用公开
    ExampleQuadParticle(ClientLevel level, double x, double y, double z, SpriteSet spriteSet) {
        // 我们使用 first 来设置初始粒子纹理
        super(level, x, y, z, spriteSet.first());
    }

    @Override
    public void tick() {
        super.tick();
        // 更新粒子图像
        this.setSpriteFromAge(spriteSet);
    }

    @Override
    public SingleQuadParticle.Layer getLayer() {
        return EXAMPLE_LAYER;
    }

    // 创建提供者
    public static class Provider implements ParticleProvider<SimpleParticleType> {

        private final SpriteSet spriteSet;

        public Provider(SpriteSet spriteSet) {
            this.spriteSet = spriteSet;
        }

        @Override
        public Particle createParticle(SimpleParticleType options, ClientLevel level, double x, double y, double z, double xd, double yd, double zd, RandomSource random) {
            // 创建粒子
            return new ExampleQuadParticle(level, x, y, z, this.spriteSet);
        }
    }
}

// 将提供者注册到 `ParticleResources#register`
// 假设可以访问 ParticleResources resources 并且 register 已设为公开
resources.register(EXAMPLE_QUAD, ExampleQuadParticle.Provider::new);

从头开始

如果要渲染更复杂或自定义的内容呢?在这些情况下,我们需要更深入地了解 ParticleEngine 如何提取粒子。Particle 类本身实际上不进行任何提取、提交或渲染。它只是每刻处理物理更新。实际的提取逻辑由 ParticleGroup 处理,而提交由 ParticleGroupRenderState 处理。

那么,什么是 ParticleGroup?顾名思义,一个粒子组持有一组粒子,并负责跟踪、Tick和提取其粒子的渲染状态。泛型表示它可以跟踪的 Particle 类型,每个组最多 16,384 个(尽管单个粒子可以通过 Particle#getParticleLimit 设置自己的子组限制)。所有 SingleQuadParticle 都是 QuadParticleGroup 的一部分。为了提取渲染状态,ParticleEngine 调用 ParticleGroup#extractRenderState,它接受当前的平截头体、相机和部分刻,并返回一个 ParticleGroupRenderState

ParticleGroupRenderState 有点像渲染状态、提交处理器和缓存的混合体。它包含两个方法:submit,接受 SubmitNodeCollector 并提交组;以及 clear,清除所有先前缓存的粒子状态。从技术上讲,任何东西都可以使用收集器提交,但粒子有 SubmitNodeCollector$ParticleGroupRenderer:一个有助于缓存和渲染的附加实用程序。组渲染器包含两个方法:prepare,将网格数据写入环形缓冲区;以及 render,通常使用缓存的缓冲区,使用提供的 RenderPass 将数据写入共享的顺序缓冲区,并将其绘制到屏幕。只有 QuadParticleRenderState 使用缓存和 ParticleGroupRenderer,因为渲染状态在渲染后立即被清除。

要将 ParticleGroup 链接到 Particle 以供使用,我们必须使用 Particle#getGroup 设置 ParticleRenderType。与之前的版本不同,ParticleRenderType 只是 ParticleGroup 的一个键。此键通过 ParticleEngine#createParticleGroup 映射到组,提交/渲染顺序由 ParticleEngine#RENDER_ORDER 确定。必须修补该方法和列表,才能使您的组正确管理粒子并提取以进行提交。

// 我们将假设我们的粒子有某个 SimpleParticleType EXAMPLE_ONE, EXAMPLE_TWO
// 此示例将构造两个具有相同基础类型的粒子,以展示组的工作原理

// 创建粒子类型
public static final ParticleRenderType EXAMPLE_TYPE = new ParticleRenderType("examplemod:example_type");

// 创建我们的粒子
public abstract class ExampleParticle extends Particle {

    // 您可以以任何方式处理传递给粒子组
    // 使字段可访问或拥有专用方法
    public final Model<Unit> model;

    protected ExampleParticle(ClientLevel level, double x, double y, double z, Function<EntityModelSet, Model<Unit>> modelFactory) {
        super(level, x, y, z);
        this.model = modelFactory.apply(Minecraft.getInstance().getEntityModels());
    }

    @Override
    public ParticleRenderType getGroup() {
        // 将粒子类型设置为我们的组
        return EXAMPLE_TYPE;
    }

    @FunctionalInterface
    public interface ExampleParticleFactory<P extends ExampleParticle> {
        
        P create(ClientLevel level, double x, double y, double z);
    }

    protected static <P extends ExampleParticle> ParticleProvider<SimpleParticleType> createProvider(ExampleParticleFactory<P> factory) {
        return (options, level, x, y, z, xd, yd, zd, random) -> factory.create(level, x, y, z);
    }
}

public class ExampleOneParticle extends ExampleParticle {

    ExampleOneParticle(ClientLevel level, double x, double y, double z) {
        super(level, x, y, z, modelSet -> new Model.Simple(new ModelPart(Collections.emptyList(), Collections.emptyMap()), RenderType::entityCutoutNoCull));
    }

    public static ParticleProvider<SimpleParticleType> provider() {
        return ExampleParticle.createProvider(ExampleOneParticle::new);
    }
}

public class ExampleTwoParticle extends ExampleParticle {

    private static final ParticleLimit LIMIT = new ParticleLimit(5);

    ExampleTwoParticle(ClientLevel level, double x, double y, double z) {
        super(level, x, y, z, modelSet -> new Model.Simple(new ModelPart(Collections.emptyList(), Collections.emptyMap()), RenderType::entityCutoutNoCull));
    }

    @Override
    public Optional<ParticleLimit> getParticleLimit() {
        // 将使用 LIMIT 子组的粒子数量限制为 5
        // 注意,由于 ParticleLimit 是一个记录,任何具有相同限制的都将被视为相同的键
        return Optional.of(LIMIT);
    }

    public static ParticleProvider<SimpleParticleType> provider() {
        return ExampleParticle.createProvider(ExampleTwoParticle::new);
    }
}

// 将提供者注册到 `ParticleResources#register`
// 假设可以访问 ParticleResources resources 并且 register 已设为公开
resources.register(EXAMPLE_ONE, ExampleOneParticle.provider());
resources.register(EXAMPLE_TWO, ExampleTwoParticle.provider());

// 创建渲染状态以提交组中的所有粒子
// 存储您需要提交到节点收集器的任何内容
public record ExampleGroupRenderState(List<Model<Unit>> models) implements ParticleGroupRenderState {

    @Override
    public void submit(SubmitNodeCollector collector) {
        // 提交每个粒子 
        for (var model : this.models) {
            collector.submitModel(model, ...);
        }
    }
}

// 创建粒子组以跟踪粒子并创建渲染状态
// EXAMPLE_ONE 和 EXAMPLE_TWO 都将被添加到此组
public class ExampleParticleGroup extends ParticleGroup<ExampleParticle> {

    public ExampleParticleGroup(ParticleEngine engine) {
        super(engine);
    }

    @Override
    public ParticleGroupRenderState extractRenderState(Frustum frustum, Camera camera, float partialTick) {
        // 创建要提交粒子的粒子组
        return new ExampleGroupRenderState(
            this.particles.stream().map(particle -> particle.model).toList()
        );
    }
}

// 将 ParticleRenderType 链接到其 ParticleGroup
// 假设我们可以访问 ParticleEngine engine
// 假设 ParticleEngine#RENDER_ORDER 是可变的并且是公开的
// 假设我们可以修补 ParticleEngine#createParticleGroup
engine.RENDER_ORDER.add(EXAMPLE_TYPE);

// 在 ParticleEngine 中
private ParticleGroup<?> createParticleGroup(ParticleRenderType renderType) {
    if (renderType == EXAMPLE_TYPE) {
        // this 指的是 ParticleEngine
        return new ExampleParticleGroup(this);
    }
    // ...
}

图集处理器整合

图集处理器已修改了一些逻辑,以整合其他精灵并更改获取 TextureAtlasSprite 的方式。

首先,地图装饰、绘画和 GUI 精灵现在是带有自己图集的适当图集:分别是 Sheets#MAP_DECORATIONS_SHEETPAINTINGS_SHEETGUI_SHEET

从这些图集中获取 TextureAtlasSprite 现在完全通过 MaterialSet 路由:一个函数式接口,接受一个 Material(基本上是图集位置和纹理位置),并返回关联的 TextureAtlasSpriteMaterialSet 处理物品模型、方块实体渲染器和实体渲染器的纹理获取:

// 这是一个从适当图集中获取苹果纹理的材质示例
public static final Material APPLE = new Material(
    TextureAtlas.LOCATION_BLOCKS, // 存储物品纹理的图集
    ResourceLocation.fromNamespaceAndPath("minecraft", "item/apple") // 根据精灵内容的纹理名称
);
// 您也可以使用 Sheets.ITEMS_MAPPER.defaultNamespaceApply("apple") 做同样的事情

// 对于某个物品模型
public class ExampleUnbakedItemModel implements ItemModel.Unbaked {
    
    // ...

    @Override
    public ItemModel bake(ItemModel.BakingContext ctx) {
        TextureAtlasSprite appleTexture = ctx.materials().get(APPLE);
        // ...
    }
}

// 对于某个特殊物品模型
public class ExampleUnbakedSpecialModel implements SpecialModelRenderer.Unbaked {
    
    // ...

    @Override
    @Nullable
    public SpecialModelRenderer<?> bake(SpecialModelRenderer.BakingContext ctx) {
        TextureAtlasSprite appleTexture = ctx.materials().get(APPLE);
        // ...
    }
}

// 对于某个方块实体渲染器
public class ExampleBlockEntityRenderer implements BlockEntityRenderer<ExampleBlockEntity> {

    public ExampleBlockEntityRenderer(BlockEntityRendererProvider.Context ctx) {
        TextureAtlasSprite appleTexture = ctx.materials().get(APPLE);
        // ...
    }

    // ...
}


// 对于某个实体渲染器
public class ExampleEntityRenderer implements EntityRenderer<ExampleEntity, ExampleEntityState> {

    public ExampleEntityRenderer(EntityRendererProvider.Context ctx) {
        TextureAtlasSprite appleTexture = ctx.getMaterials().get(APPLE);
        // ...
    }

    // ...
}
  • assets/minecraft/shaders/core
    • blit_screen.json -> screenquad.json,使用无格式三角形而不是定位四边形
    • position_color_lightmap.* 已移除
    • position_color_tex_lightmap.* 已移除
  • com.mojang.blaze3d.vertex
    • CompactVectorArray - 一个将浮点向量列表压缩到单个顺序数组中的持有者。
    • MeshData$SortState#centroids 现在返回一个 CompactVectorArray
    • VertexSorting
      • byDistance 现在接受一个 Vector3fc 而不是 Vector3f
      • sort 现在接受一个 CompactVectorArray 而不是 Vector3f[]
  • net.minecraft.client.Minecraft
    • getTextureAtlas -> AtlasManager#getAtlasOrThrow,不是一对一
    • getPaintingTexturesgetMapDecorationTexturesgetGuiSprites -> getAtlasManager,不是一对一
  • net.minecraft.client.animation.Keyframe 现在有一个重载,接受 preTargetpostTarget 而不是一个简单的 target,接受 Vector3fc 而不是 Vector3f
  • net.minecraft.client.entity
    • ClientAvatarEntity - 化身实体的客户端数据。
    • ClientAvatarState - 化身的移动状态。
    • ClientMannequin - Mannequin 实体的客户端版本。
  • net.minecraft.client.gui
    • GuiGraphics
      • renderOutline -> submitOutline
      • renderDeferredTooltip -> renderDeferredElements,不是一对一
      • submitBannerPatternRenderState 现在接受 BannerFlagModel 而不是 ModelPart GuiSpriteManager 类已移除
  • net.minecraft.client.gui.render.GuiRenderer 现在接受 SubmitNodeCollectorFeatureRenderDispatcher
    • MIN_GUI_Z 现在是公开的
  • net.minecraft.client.gui.render.pip
    • GuiBannerResultRenderer 现在接受一个 MaterialSet
    • GuiSignRenderer 现在接受一个 MaterialSet
  • net.minecraft.client.gui.render.state.TiledBlitRenderState - 一个用于使用平铺构建精灵的渲染状态,通常用于平铺或九切片纹理。
  • net.minecraft.client.gui.render.state.pip.GuiBannerResultRenderState 现在接受 BannerFlagModel 而不是 ModelPart
  • net.minecraft.client.model
    • AbstractPiglinModel#createArmorMeshSet - 为每个人形盔甲槽位创建模型网格。
    • ArmedModel 现在有一个 EntityRenderState 的泛型
      • translateToHand 现在接受实体渲染状态
    • ArmorStandArmorModel#createBodyLayer -> createArmorLayerSet,不是一对一
    • BellModel$State - 表示支持对象的状态。
    • BookModel$State - 表示支持对象的状态。
    • BreezeModel
      • createBodyLayer -> createBaseMesh,现在是私有的
        • createBodyLayercreateWindLayercreateEyesLayer 取代
    • CopperGolemModel - 铜傀儡实体的模型。
    • CopperGolemStatueModel - 铜傀儡雕像的模型。
    • CreakingModel
      • NO_PARTSgetHeadModelParts 已移除
      • createEyesLayer - 创建模型的眼睛。
    • EntityModel#setupAnim -> Model#setupAnim
    • GuardianParticleModel - 从守卫者生成的粒子。
    • HeadedModel#translateToHead - 将姿势堆栈变换到头部的位置和旋转。
    • HumanoidArmorModel -> HumanoidModel#createArmorMeshSet,不是一对一
    • HumanoidModel#copyPropertiesTo 已移除
    • Model 现在接受一个表示渲染状态的泛型
    • PlayerCapeModel 现在继承 PlayerModel
    • PlayerEarsModel 现在继承 PlayerModel
    • PlayerModel 渲染状态已拓宽到 AvatarRenderState
      • 静态字段现在是 protected
      • createArmorMeshSet - 为每个人形盔甲槽位创建模型网格。
    • SkullModelBase$State - 表示支持对象的状态。
    • SpinAttackEffectModel 泛型已拓宽到 AvatarRenderState
    • VillagerLikeModel 现在接受渲染状态的泛型
      • hatVisible 已移除
        • VillagerModel#createNoHatModel 取代
      • translateToArms 现在接受渲染状态
    • WardenModel
      • createTendrilsLayercreateHeartLayercreateBioluminescentLayercreatePulsatingSpotsLayer - 创建监守者的 RenderLayer 使用的层。
      • getTendrilsLayerModelPartsgetHeartLayerModelPartsgetBioluminescentLayerModelPartsgetPulsatingSpotsLayerModelParts 已移除
    • ZombieVillagerModel
      • createArmorLayer -> createArmorLayerSet,不是一对一
      • createNoHatLayer - 创建没有帽子层的模型。
  • net.minecraft.client.model.geom.ModelPart
    • copyFrom 已移除
    • $Polygon#normal 现在是 Vector3fc 而不是 Vector3f
    • $Vertex
      • pos -> xyz
      • worldXworldYworldZ - 返回坐标缩小 16 倍后的值。
  • net.minecraft.client.model.geom.builders.PartDefinition
    • clearRecursively - 清除所有子部件及其子子部件。
    • retainPartsAndChildren - 从其根和任何子子部件中保留指定的部件。
    • retainExactParts - 仅保留顶级部件,清除所有其他部件和子子部件。
  • net.minecraft.client.particle
    • AttackSweepParticle 现在继承 SingleQuadParticle
    • BaseAshSmokeParticle 现在继承 SingleQuadParticle 并且是 abstract
    • BlockMarker 现在继承 SingleQuadParticle
    • BreakingItemParticle 现在继承 SingleQuadParticle
      • 构造函数接受 TextureAtlasSprite 而不是 ItemStackRenderState
      • $ItemParticleProvider#calculateState -> getSprite,不是一对一
    • BubbleColumnUpParticle 现在继承 SingleQuadParticle
    • BubbleParticle 现在继承 SingleQuadParticle
    • BubblePopParticle 现在继承 SingleQuadParticle
    • CampfireSmokeParticle 现在继承 SingleQuadParticle
    • CritParticle 现在继承 SingleQuadParticle
    • DragonBreathParticle 现在继承 SingleQuadParticle
      • $Provider 泛型现在使用 PowerParticleOption
    • DripParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
      • create*Particle 方法 -> $*Provider
    • DustParticleBase 现在继承 SingleQuadParticle
    • ElderGuardianParticleGroup - 负责设置和提交远古守卫者粒子的粒子组。
    • ExplodeParticle 现在继承 SingleQuadParticle
    • FallingDustParticle 现在继承 SingleQuadParticle
    • FallingLeavesParticle 现在继承 SingleQuadParticle 并接受 TextureAtlasSprite 而不是 SpriteSet
    • FireflyParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • FireworkParticles
      • $FlashProvider 泛型现在使用 ColorParticleOption
      • $OverlayParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • FlameParticle 现在接受一个 TextureAtlasSprite
    • FlyStraightTowardsParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • FlyTowardsPositionParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • GlowParticle 现在继承 SingleQuadParticle
    • GustParticle 现在继承 SingleQuadParticle
    • HeartParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • HugeExplosionParticle 现在继承 SingleQuadParticle
    • ItemPickupParticle 现在接受 EntityRenderState 而不是 EntityRenderDispatcher
      • 除目标实体外,所有字段现在都是 protected
    • ItemPickupParticleGroup - 负责设置和提交物品拾取粒子的粒子组。
    • LavaParticle 现在继承 SingleQuadParticle
    • MobAppearanceParticle -> ElderGuardianParticle
    • NoRenderParticleGroup - 什么都不做的粒子组。
    • NoteParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • Particle
      • rColgColbColalpha -> SingleQuadParticle#rColgColbColalpha
      • rolloRoll -> SingleQuadParticle#rolloRoll
      • setColorsetAlpha -> SingleQuadParticle#setColorsetAlpha
      • renderrenderCustom -> ParticleGroupRenderState#submit,不是一对一
      • getRenderType -> getGroup
        • 此方法的原始用途已移至 SingleQuadParticle#getLayer
      • getParticleGroup -> getParticleLimit,不是一对一
    • ParticleEngine 不再实现 PreparableReloadListener
      • 构造函数现在接受 ParticleResources 而不是 TextureManager
      • close 已移除
      • updateCount 现在是 protected
      • render -> extract,不是一对一
      • destroy -> ClientLevel#addDestroyBlockEffect
      • crack -> ClientLevel#addBreakingBlockEffect
      • clearParticles 现在是 public
      • $MutableSpriteSet -> ParticleResources$MutableSpriteSet
      • $SpriteParticleRegistration -> ParticleResources$SpriteParticleRegistration
    • ParticleGroup - 特定 ParticleRenderType 的粒子持有者,负责Tick和提取通用渲染状态。
    • ParticleProvider
      • createParticle 现在接受 RandomSource
      • $Sprite#createParticle 现在接受 RandomSource 并返回 SingleQuadParticle 而不是 TextureSheetParticle
    • ParticleRenderType 不再接受 RenderType
      • 此记录已被重新用于表示粒子组的键
      • TERRAIN_SHEET -> SingleQuadParticle$Layer#TERRAIN
      • PARTICLE_SHEET_OPAQUE -> SingleQuadParticle$Layer#OPAQUE
      • PARTICLE_SHEET_TRANSLUCENT -> SingleQuadParticle$Layer#TRANSLUCENT
      • CUSTOM 被一个不是为 ParticleRenderType#SINGLE_QUADS 的粒子组取代
    • ParticleResources - 加载粒子提供者、任何必要的描述,并将它们计算到所需的精灵集中。
    • PlayerCloudParticle 现在继承 SingleQuadParticle
    • PortalParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • QuadParticleGroup - 负责设置和提交单个四边形粒子的粒子组。
    • ReversePortalParticle 现在接受一个 TextureAtlasSprite
    • RisingParticle 现在继承 SingleQuadParticle
    • SculkChargeParticle 现在继承 SingleQuadParticle
    • SculkChargePopParticle 现在继承 SingleQuadParticle
    • SculkChargePopParticle 现在继承 SingleQuadParticle
    • ShriekParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • SimpleAnimatedParticle 现在继承 SingleQuadParticle 并且是 abstract
    • SingleQuadParticle 现在接受一个 TextureAtlasSprite
      • sprite - 粒子的纹理。
      • render -> extract,不是一对一,现在接受 QuadParticleRenderState 而不是 VertexConsumer
      • renderRotatedQuad -> extractRotatedQuad,不是一对一,现在接受 QuadParticleRenderState 而不是 VertexConsumer
      • getU0getU1getV0getV1 不再是抽象的
      • getLayer - 设置单个四边形的渲染层。
      • $Layer - 单个四边形应渲染的层。
    • SnowflakeParticle 现在继承 SingleQuadParticle
    • SpellParticle 现在继承 SingleQuadParticle
      • InstantProvider 泛型现在使用 SpellParticleOption
    • SplashParticle 现在接受一个 TextureAtlasSprite
    • SpriteSet#first - 返回精灵集中的第一个纹理。
    • SuspendedParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • SuspendedTownParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • TerrainParticle 现在继承 SingleQuadParticle
    • TextureSheetParticle 类已移除,请改用 SingleQuadParticle
    • TrailParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • TrialSpawnerDetectionParticle 现在继承 SingleQuadParticle
    • VibrationSignalParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • WakeParticle 现在继承 SingleQuadParticle
    • WaterCurrentDownParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
    • WaterDropParticle 现在继承 SingleQuadParticle 并接受一个 TextureAtlasSprite
  • net.minecraft.client.player.AbstractClientPlayer 字段现在存储在 ClientAvatarState
    • elytraRot* -> *Cloak
    • clientLevel 已移除
    • getDeltaMovementLerped -> addWalkedDistance,不是一对一
    • updateBob - 更新相机的摆动运动。
  • net.minecraft.client.renderer
    • EndFlashState - 末地闪光的渲染状态。
    • GameRenderer 现在接受 BlockRenderDispatcher
      • getSubmitNodeStorage - 获取用于功能类对象的节点提交。
      • getFeatureRenderDispatcher - 获取用于渲染功能类对象的分派器。
      • getLevelRenderState - 获取等级中动态功能的渲染状态。
    • ItemInHandRenderer
      • renderItem 现在接受 SubmitNodeCollector 而不是 MultiBufferSource
      • renderHandsWithItems 现在接受 SubmitNodeCollector 而不是 MultiBufferSource$BufferSource
    • LevelRenderer 现在接受 LevelRenderStateFeatureRenderDispatcher
      • getSectionRenderDispatcher 现在可为 null
      • tickParticles 已移除
      • addParticle 已移除
    • MapRenderer 现在接受 AtlasManager 而不是 MapDecorationTextureManager
      • render 现在接受 SubmitNodeCollector 而不是 MultiBufferSource
    • OrderedSubmitNodeCollector - 一个提交处理器,用于在功能被分派时以给定顺序将元素绘制到屏幕。
    • OutlineBufferSource 不再接受任何参数
      • setColor 现在接受一个整数
    • ParticleGroupRenderState - 一组粒子的渲染状态。
    • ParticlesRenderState - 所有粒子的渲染状态。
    • QuadParticleRenderState - 所有单个四边形粒子的渲染组状态。
    • RenderPipelines
      • GUI_TEXT - GUI 中文本的管线。
      • GUI_TEXT_INTENSITY - GUI 中未着色文本的强度管线。
    • RenderStateShard#TRANSLUCENT_TARGETPARTICLES_TARGET 已移除
    • RenderType
      • pipeline - 该类型使用的 RenderPipeline
      • opaqueParticletranslucentParticle 已移除
      • sunriseSunsetcelestial 已移除
    • ScreenEffectRenderer 现在接受一个 MaterialSet
      • renderScreenEffect 现在接受一个 SubmitNodeCollector
    • ShapeRenderer
      • renderLineBox 现在接受 PoseStack$Pose 而不是 PoseStack
      • renderFace 现在接受 Matrix4f 而不是 PoseStack
    • Sheets
      • GUI_SHEETMAP_DECORATIONS_SHEETPAINTINGS_SHEET - 图集纹理。
      • BLOCK_ENTITIES_MAPPER - 将方块纹理映射到方块实体的映射器。
      • *COPPER* - 铜箱子的材质。
      • chooseMaterial 现在接受 ChestRenderState$ChestMaterialType 而不是 BlockEntityboolean
    • SkyRenderer
      • END_SKY_LOCATION 现在是私有的
      • renderSunMoonAndStars 不再接受缓冲区源
      • renderEndFlash 不再接受缓冲区源
      • renderSunriseAndSunset 不再接受缓冲区源
    • SpecialBlockModelRenderer
      • vanilla 现在接受 SpecialModelRenderer$BakingContext 而不是 EntityModelSet
      • renderByBlock 现在接受 SubmitNodeCollector 而不是 MultiBufferSource,以及一个轮廓颜色
    • SubmitNodeCollection - OrderedSubmitNodeCollector 的一个实现,将提交的功能保存在单独的列表中。
    • SubmitNodeCollector - 一个 OrderedSubmitNodeCollector,提供更改元素将渲染的当前顺序的方法。
    • SubmitNodeStorage - 由某个顺序持有的集合的存储。
    • SkyRenderer
      • renderEndFlash - 渲染末地闪光。
      • initTextures - 获取所用元素的纹理。
      • extractRenderState - 从当前等级提取 SkyRenderState
    • WeatherEffectRenderer
      • render 现在接受 WeatherRenderState 而不是 intfloatLevel
        • 这些字段已移至 extractRenderState
      • extractRenderState - 从当前等级提取 WeatherRenderState
      • $ColumnInstance 现在是公开的
    • WorldBorderRenderer
      • render 现在接受 WorldBorderRenderState 而不是 WorldBorder
      • extract - 从当前世界边界提取 WorldBorderRenderState
  • net.minecraft.client.renderer.block
    • BlockRenderDispatcher 现在接受一个 MaterialSet
    • MovingBlockRenderState - 一个实现 BlockAndTintGetter 的移动方块的渲染状态。
    • LiquidBlockRenderer#setupSprites 现在接受 BlockModelShaperMaterialSet
  • net.minecraft.client.renderer.blockentity
    • 这里的大多数接受 MultiBufferSource 的方法已被 SubmitNodeCollector 取代,如果该方法不用于物品渲染,则还有 ModelFeatureRenderer$CrumblingOverlay
    • 大多数方法从 render* 更名为 submit*,主要的 submit 方法现在使用 BlockEntityRenderState
    • 所有 BlockEntityRenderer 现在都有一个 BlockEntityRenderState 泛型
    • AbstractEndPortalRenderer - 末地传送门的方块实体渲染器。
    • AbstractSignRenderer
      • getSignModel 现在返回一个 Model$Simple
      • renderSign -> submitSign,现在接受一个 Model$Simple 并且不再接受色调颜色
    • BannerRenderer 有一个接受 SpecialModelRenderer$BakingContext 的重载
      • EntityModelSet 构造函数现在接受 MaterialSet
      • renderPatterns -> submitPatterns 现在接受 MaterialSetModelFeatureRenderer$CrumblingOverlayModelPart 已被 Model 及其渲染状态取代,一个 boolean 表示是否使用实体闪光,以及一个轮廓颜色
        • 带有两个额外 boolean 的重载已移除
      • renderSpecial -> submitSpecial,现在接受轮廓颜色
    • BeaconRenderer#renderBeaconBeam -> submitBeaconBeam,不再接受游戏时间 long
    • BedRenderer 有一个接受 SpecialModelRenderer$BakingContext 的重载
      • EntityModelSet 构造函数现在接受 MaterialSet
      • renderSpecial -> submitSpecial,现在接受轮廓颜色
    • BlockEntityRenderDispatcher 现在接受 MaterialSetPlayerSkinRenderCache
      • render -> submit,现在接受 BlockEntityRenderState 而不是 BlockEntity,不再接受部分刻 float,并接受 CameraRenderState
      • getRenderer 现在有一个重载,可以从其 BlockEntityRenderState 获取渲染器
      • tryExtractRenderState - 从 BlockEntity 获取 BlockEntityRenderState
      • levelcameracameraHitResult 已移除
      • prepare 现在只接受 Camera
      • setLevel 已移除
    • BlockEntityRenderer 现在有另一个泛型 S 表示 BlockEntityRenderState
      • render -> submit,接受 BlockEntityRenderStatePoseStackSubmitNodeCollectorCameraRenderState
      • createRenderState - 创建渲染状态对象。
      • extractRenderState - 从方块实体中提取渲染状态。
    • BlockEntityRendererProvider$Context 现在是一个记录,接受 MaterialSetPlayerSkinRenderCache
      • 它现在有另一个泛型 S 表示 BlockEntityRenderState
    • CopperGolemStatueBlockRenderer - 铜傀儡雕像的方块实体渲染器。
    • DecoratedPotRenderer 有一个接受 SpecialModelRenderer$BakingContext 的重载
      • EntityModelSet 构造函数现在接受 MaterialSet
      • render 重载 -> submit,现在接受轮廓颜色
    • HangingSignRenderer
      • createSignModel 现在返回一个 Model$Simple
      • renderInHand 现在接受一个 MaterialSet
    • ShelfRenderer - 架子的方块实体渲染器。
    • ShulkerBoxRenderer 有一个接受 SpecialModelRenderer$BakingContext 的重载
      • EntityModelSet 构造函数现在接受 MaterialSet
      • render 重载 -> submit,现在接受轮廓颜色
    • SignRenderer
      • createSignModel 现在返回一个 Model$Simple
      • renderInHand 现在接受一个 MaterialSet
    • SkullBlockRenderer#submitSkull - 将骷髅头模型提交给收集器。
    • SpawnerRenderer#renderEntityInSpawner -> submitEntityInSpawner,现在接受 CameraRenderState
    • TestInstanceREnderer 现在接受 BlockEntityRendererProvider$Context
  • net.minecraft.client.renderer.blockentity.state
    • BannerRenderState - 旗帜方块实体的渲染状态。
    • BeaconRenderState - 信标方块实体的渲染状态。
    • BedRenderState - 床方块实体的渲染状态。
    • BellRenderState - 钟方块实体的渲染状态。
    • BlockEntityRenderState - 所有方块实体的基础渲染状态。
    • BlockEntityWithBoundingBoxRenderState - 具有自定义边界框的方块实体的渲染状态。
    • BrushableBlockRenderState - 可刷扫方块实体的渲染状态。
    • CampfireRenderState - 营火方块实体的渲染状态。
    • ChestRenderState - 箱子方块实体的渲染状态。
    • CondiutRenderState - 潮涌核心方块实体的渲染状态。
    • CopperGolemStatueRenderState - 铜傀儡方块实体的渲染状态。
    • DecoratedPotRenderState - 饰纹陶罐方块实体的渲染状态。
    • EnchantTableRenderState - 附魔台方块实体的渲染状态。
    • EndGatewayRenderState - 末地折跃门方块实体的渲染状态。
    • EndPortalRenderState - 末地传送门方块实体的渲染状态。
    • LecternRenderState - 讲台方块实体的渲染状态。
    • PistonHeadRenderState - 活塞头方块实体的渲染状态。
    • ShelfRenderState - 架子方块实体的渲染状态。
    • ShulkerBoxRenderState - 潜影盒方块实体的渲染状态。
    • SignRenderState - 告示牌方块实体的渲染状态。
    • SkullBlockRenderState - 骷髅头方块实体的渲染状态。
    • SpawnerRenderState - 刷怪笼方块实体的渲染状态。
    • TestInstanceRenderState - 测试实例方块实体的渲染状态。
    • VaultRenderState - vault 方块实体的渲染状态。
  • net.minecraft.client.renderer.culling.Frustum
    • offset - 偏移位置。
    • pointInFrustum - 检查提供的坐标是否在平截头体内。
  • net.minecraft.client.renderer.entity
    • 这里的大多数接受 MultiBufferSource 和光照坐标整数的方法已被 SubmitNodeCollector 和渲染状态参数取代
    • 大多数方法从 render* 更名为 submit*
    • AbstractBoatRenderer#renderTypeAdditions -> submitTypeAdditions
    • AbstractMinecartRenderer#renderMinecartContents -> submitMinecartContents
    • AbstractSkeletonRenderer 接受 ArmorModelSet 而不是 ModelLayerLocation
    • AbstractZombieRenderer 接受 ArmorModelSet 而不是模型
    • ArmorModelSet - 一个将某个对象映射到每个人形盔甲槽位的持有者。通常保存层定义,然后将其烘焙到关联的模型中。
    • BreezeRenderer#enable 已移除
    • CopperGolemRenderer - 铜傀儡实体的渲染器。
    • DisplayRenderer#renderInner -> submitInner
    • EnderDragonRenderer#renderCrystalBeams -> submitCrystalBeams
    • EntityRenderDispatcher 现在接受 AtlasManager
      • prepare 不再接受 Level
      • setRenderShadowsetRenderHitBoxesshouldRenderHitBoxes 已移除
      • extractEntity - 从实体和部分刻创建渲染状态。
      • render -> submit,现在接受 CameraRenderState
      • setLevel -> resetCamera,不是一对一
      • getPlayerRenderer - 从给定的客户端玩家获取 AvatarRenderer
      • overrideCameraOrientationdistanceToSqrcameraOrientation 已移除
    • EntityRenderer
      • NAMETAG_SCALE 现在是公开的
      • render(S, PoseStack, MultiBufferSource, int) -> submit(S, PoseStack, SubmitNodeCollector, CameraRenderState)
      • renderNameTag -> submitNameTag,现在接受 CameraRenderState
      • finalizeRenderState - 在 extractRenderState 之后作为最后一步提取渲染状态的信息,例如阴影。
    • EntityRendererProvider$Context 现在接受 PlayerSkinRenderCacheAtlasManager
      • getModelManager 已移除
      • getMaterials - 返回材质到图集精灵的映射器。
      • getPlayerSkinRenderCache - 获取玩家皮肤的渲染缓存。
      • getAtlas - 返回该位置的图集。
    • EntityRenderers#createPlayerRenderers 现在返回一个 PlayerModelTypeAvatarRenderer 的映射
    • ItemEntityRenderer
      • renderMultipleFromCount -> submitMultipleFromCount
      • renderMultipleFromCount(PoseStack, MultiBufferSource, int, ItemClusterRenderState, RandomSource) -> renderMultipleFromCount(PoseStack, SubmitNodeCollector, int, ItemClusterRenderState, RandomSource)
    • ItemRenderer 不再接受 ItemModelResolver
      • getArmorFoilBuffer -> getFoilRenderTypes,不是一对一
      • renderStatic 方法已移除
    • MobRenderer#checkMagicName - 返回自定义名称是否与给定字符串匹配。
    • PiglinRenderer 接受 ArmorModelSet 而不是 ModelLayerLocation
    • TntMinecartRenderer#renderWhiteSolidBlock -> submitWhiteSolidBlock,现在接受一个轮廓颜色
    • ZombieRenderer 接受 ArmorModelSet 而不是 ModelLayerLocation
    • ZombifiedPiglinPiglinRenderer 接受 ArmorModelSet 而不是 ModelLayerLocation
  • net.minecraft.client.renderer.entity.layers
    • ArrowLayer 现在处理 AvatarRenderState 而不是 PlayerRenderState
    • BeeStingerLayer 现在处理 AvatarRenderState 而不是 PlayerRenderState
    • BlockDecorationLayer - 一个处理由实体变换的方块模型的层。
    • BreezeWindLayer 现在接受 EntityModelSet 而不是 EntityRendererProvider$Context
    • CapeLayer 现在处理 AvatarRenderState 而不是 PlayerRenderState
    • CustomHeadLayer 现在接受 PlayerSkinRenderCache
    • Deadmau5EarsLayer 现在处理 AvatarRenderState 而不是 PlayerRenderState
    • EquipmentLayerRenderer#renderLayers 现在接受渲染状态、SubmitNodeCollector、轮廓颜色和一个初始顺序,而不是 MultiBufferSource
    • HumanoidArmorLayer 现在接受 ArmorModelSet 而不是模型
      • setPartVisibility 已移除
    • ItemInHandLayer#renderArmWithItem -> submitArmWithItem
    • LivingEntityEmissiveLayer 现在接受一个用于纹理的函数而不是 ResourceLocation,以及一个模型而不是 $DrawSelector
      • $DrawSelector 已移除
    • ParrotOnShoulderLayer 现在处理 AvatarRenderState 而不是 PlayerRenderState
    • PlayerItemInHandLayer 现在处理 AvatarRenderState 而不是 PlayerRenderState
    • RenderLayer
      • renderColoredCutoutModelcoloredCutoutModelCopyLayerRender 现在接受 Model 而不是 EntityModel,接受 SubmitNodeCollector 而不是 MultiBufferSource,以及一个表示渲染顺序的整数
      • render -> submit,接受 SubmitNodeCollector 而不是 MultiBufferSource
    • SimpleEquipmentLayer 现在接受一个顺序整数
    • SpinAttackEffectLayer 现在处理 AvatarRenderState 而不是 PlayerRenderState
    • StuckInBodyLayer 现在有一个用于渲染状态的额外泛型,在构造函数中也接受渲染状态
      • numStuck 现在接受 AvatarRenderState 而不是 PlayerRenderState
    • VillagerProfessionLayer 现在接受两个模型
  • net.minecraft.client.renderer.entity.player.PlayerRenderer -> AvatarRenderer
    • render*Hand 现在接受 SubmitNodeCollector 而不是 MultiBufferSource
  • net.minecraft.client.renderer.entity.state
    • CopperGolemRenderState - 铜傀儡实体的渲染状态。
    • DisplayEntityRenderState#cameraYRotcameraXRot - 相机的旋转。
    • EntityRenderState
      • NO_OUTLINE - 一个表示无轮廓颜色的常量。
      • outlineColor - 实体的轮廓颜色。
      • lightCoords - 用于照亮实体的打包光照坐标。
      • shadowPieces$ShadowPiece - 表示实体投射的阴影的相对坐标。
    • FallingBlockRenderState 字段和实现已全部移至 MovingBlockRenderState
    • LivingEntityRenderState
      • appearsGlowing -> EntityRenderState#appearsGlowing,现在是一个方法
      • customName 已移除
    • PaintingRenderState#lightCoords -> lightCoordsPerBlock
    • PlayerRenderState -> AvatarRenderState
      • useItemRemainingTicksswinging 已移除
      • showDeadMouseEars -> showExtraEars
    • SheepRenderState
      • id 已移除
      • isJebSheep 现在是一个字段而不是方法
    • WitherSkullRenderState#xRotyRot -> modeState,不是一对一
  • net.minecraft.client.renderer.feature
    • BlockFeatureRenderer - 渲染提交的方块、方块模型或下落中的方块。
    • CustomFeatureRenderer - 通过传递的函数渲染提交的几何体。
    • FeatureRenderDispatcher - 分派所有功能以从提交的节点收集器对象渲染。
    • FlameFeatureRenderer - 渲染提交的着火的实体动画。
    • HitboxFeatureRenderer - 渲染提交的实体碰撞箱。
    • ItemFeatureRenderer - 渲染提交的物品。
    • LeashFeatureRenderer - 渲染提交的附着在实体上的拴绳。
    • ModelFeatureRenderer - 渲染提交的 Model
    • ModelPartFeatureRenderer - 渲染提交的 ModelPart
    • NameTagFeatureRenderer - 渲染提交的名称标签。
    • ParticleFeatureRenderer - 渲染提交的粒子。
    • ShadowFeatureRenderer - 渲染提交的实体阴影。
    • TextFeatureRenderer - 渲染提交的文本。
  • net.minecraft.client.renderer.item
    • ItemModel$BakingContext 现在接受 MaterialSetPlayerSkinRenderCache,并实现 SpecialModelRenderer$BakingContext
    • ItemStackRenderState#render -> submit,接受 SubmitNodeCollector 而不是 MultiBufferSource 以及一个轮廓颜色
  • net.minecraft.client.renderer.special
    • 这里的大多数接受 MultiBufferSource 的方法已被 SubmitNodeCollector 取代
    • ChestSpecialRenderer 现在接受一个 MaterialSet
      • *COPPER* - 铜箱子的纹理。
    • ConduitSpecialRenderer 现在接受一个 MaterialSet
    • CopperGolemStatueSpecialRenderer - 铜傀儡雕像作为物品的特殊渲染器。
    • HangingSignSpecialRenderer 现在接受一个 MaterialSet 和一个 Model$Simple 而不是 Model
    • NoDataSpecialModelRenderer#render -> submit,现在接受一个轮廓颜色
    • PlayerHeadSpecialRenderer 现在接受 PlayerSkinRenderCache
    • ShieldSpecialRenderer 现在接受一个 MaterialSet
    • SpecialModelRenderer
      • render -> submit,现在接受一个轮廓颜色
      • $BakingContext - 用于烘焙特殊物品模型的上下文。
      • $Unbaked#bake 现在接受 SpecialModelRenderer$BakingContext 而不是 EntityModelSet
    • SpecialModelRenderers#createBlockRenderers 现在接受 SpecialModelRenderer$BakingContext 而不是 EntityModelSet
    • StandingSignSpecialRenderer 现在接受一个 MaterialSet 和一个 Model$Simple 而不是 Model
  • net.minecraft.client.renderer.state
    • BlockBreakingRenderState - 当前方块被破坏进度的渲染状态。
    • BlockOutlineRenderState - 通过其 VoxelShape 的方块轮廓的渲染状态。
    • CameraRenderState - 相机的渲染状态。
    • LevelRenderState - 等级中动态功能的渲染状态。
    • ParticleGroupRenderState - 一组粒子的渲染状态。
    • ParticlesRenderState - 所有粒子的渲染状态。
    • QuadParticleRenderState - 所有单个四边形粒子的渲染组状态。
    • SkyRenderState - 天空的渲染状态,包括月亮和星星。
    • WeatherRenderState - 当前天气的渲染状态。
    • WorldBorderRenderState - 世界边界的渲染状态。
  • net.minecraft.client.renderer.texture
    • SkinTextureDownloader 现在是一个实例类而不是静态方法持有者,接受 ProxyTextureManager 和主线程 Executor
      • 以前是静态的大多数方法现在是实例方法
    • SpriteContents 现在接受一个可选的 AnimationMetadataSectionMetadataSectionType$WithValue 列表,而不是 ResourceMetadata
      • metadata -> getAdditionalMetadata,不是一对一
    • SpriteLoader
      • DEFAULT_METADATA_SECTIONS 已移除
      • stitch 现在是私有的
      • runSpriteSuppliers 现在是私有的
      • loadAndStitch(ResourceManager, ResourceLocation, int, Executor) 已移除
      • loadAndStitch 现在接受一组 MetadataSectionType 而不是一个集合
      • $Preparations
        • waitForUpload 已移除
        • getSprite - 返回给定资源位置的图集精灵。
    • TextureAtlasSprite#isAnimated -> SpriteContents#isAnimated
  • net.minecraft.client.renderer.texture.atlas.SpriteResourceLoader#create 现在接受一组 MetadataSectionType 而不是一个集合
  • net.minecraft.client.resources
    • MapDecorationTextureManager 类已移除
    • PaintingTextureManager 类已移除
    • PlayerSkin$Model -> PlayerModelType,不是一对一
      • 构造函数现在接受遗留服务名称
      • byName -> byLegacyServicesName
    • SkinManager 现在接受 Services 而不是 MinecraftSessionService,以及一个 SkinTextureDownloader
      • lookupInsecure -> createLookup,现在接受一个布尔值表示是否检查不安全的皮肤
      • getOrLoad -> get
    • TextureAtlasHolder 类已移除
  • net.minecraft.client.resources.model
    • AtlasIds -> net.minecraft.data.AtlasIds
    • AtlasSet -> AtlasManager,不是一对一
      • forEach - 遍历每个图集图版。
    • Material
      • sprite -> MaterialSet#get
      • buffer 现在接受一个 MaterialSet
    • MaterialSet - 材质到其图集精灵的映射。
    • ModelBakery 现在接受 MaterialSetPlayerSkinRenderCache
    • ModelManager 不再是 AutoCloseable
      • 构造函数接受 PlayerSkinRenderCacheAtlasManager 而不是 TextureManager,以及最大 mipmap 级别整数
      • getAtlas -> MaterialSet#get
      • updateMaxMipLevel -> AtlasManager#updateMaxMipLevel
  • net.minecraft.core.particles
    • ParticleGroup -> ParticleLimit
    • ParticleTypes
      • DRAGON_BREATH 现在使用 PowerParticleOption
      • EFFECT 现在使用 SpellParticleOption
      • FLASH 现在使用 ColorParticleOption
      • INSTANT_EFFECT 现在使用 SpellParticleOption
    • PowerParticleOption - 龙息粒子的粒子选项。
    • SpellParticleOption - 药水效果的粒子选项。

字体 字形 管线

字形的后端已被部分重做,以将字符及其效果统一到一个可渲染的对象,并添加烘焙流程(尽管是延迟的)。本文将简要概述这个新流程。

让我们从资源重新加载时开始,导致 FontManager 运行。字体定义被加载并传递到它们适当的 GlyphProviderDefinition,对于这个例子,它将立即解包到 GlyphProvider$Loader 中。加载器读取它需要的任何信息(很可能是纹理),并将其映射到关联的码点作为 UnbakedGlyph。一个 UnbakedGlyph 表示一个包含其 GlyphInfo(带有位置元数据)的单个字符,以及一个将其写入纹理的 bake 方法。bake 接受一个 UnbakedGlyph$Stitcher,它本身接受一个 GlyphBitmap 以正确定位和上传字形,以及用于任何偏移调整的 GlyphInfo。然后,在解析和最终确定之后,使用 FontSet#reload 创建 FontSet。这会重置纹理和缓存,并调用 FontSet#selectProviders 来存储活动的 GlyphProvider 列表,并通过将字符宽度映射到匹配的码点列表来填充 glyphsByWidth。此时,所有加载都已完成。虽然字形以未烘焙的格式存储,但它们直到该特定字符被渲染时才被烘焙和缓存。

现在,让我们转到 FontDescriptionFontDescription 提供了与 GlyphSource 的一对一映射,后者负责获取字形。原版提供了三种 FontDescription$Resource 用于映射到如上所述的 FontSet(字体 JSON 名称),$AtlasSprite 用于将图集解释为一组字形,以及 $PlayerSprite 用于渲染玩家头部和帽子。对于给定的 Component,可以通过 Style#withFont 将使用的 FontDescription 设置为其 Style

因此,假设您使用 FontDescription#DEFAULT 将文本绘制到屏幕,它使用定义的 assets/minecraft/font/default.json。最终,这将调用 Font#drawInBatchdrawInBatch8xOutline。然后,无论是通过 StringSplitter 还是直接,GlyphSource 都是从 FontDescription 获得的。然后,调用 GlyphSource#getGlyph。对于 FontDescription$AtlasSprite$PlayerSprite,这仅返回相关纹理的包装器。对于 $Resource,这内部调用 FontSet#getGlyph,它将 UnbakedGlyph 存储为 FontSet$DelayedBake 的一部分,然后通过调用 UnbakedGlyph#bake 将字形写入某个纹理,立即将其解析为 BakedGlyph

BakedGlyph 包含两个方法:如前所述的用于位置元数据的 GlyphInfo,以及一个称为 createGlyph 的方法,它返回一个 TextRenderable:一个用于将字形绘制到屏幕的渲染器。TextRenderable 还有一个子接口,称为 PlainTextRenderable,用于帮助处理纹理精灵。在内部,所有资源 BakedGlyph 都是 BakedSheetGlyph,因为 UnbakedGlyph$Stitcher#stitch 调用只是包装了 GlyphStitcher#stitch。您可以将 BakedSheetGlyph 视为 256x256 FontTexture 上的一个视图,如果一张 FontTexture 上没有足够的空间,则会创建一个新的 FontTexture

BakedSheetGlyph 还实现了 EffectGlyph,它可能应该在文本上渲染某种效果。这个功能,虽然目前仅作为另一个对象实现,但仅用于白色字形,而白色字形未被使用。

对象信息

ObjectInfo 是服务器端的实现,用于构造通过字形管线渲染任意对象所使用的 FontDescription。每个 info 接受 FontDescription 和一个常规的 String 来显示简单的描述。此外,它接受一个 MapCodec 来从对象内容进行编码和解码。

请注意,要使自定义 FontDescription 正确映射到源,您需要以某种方式修改 FontManager$CachedFontProvider#getGlyphSource 或实现自定义的 Font$Provider

// 一个基本的字体描述
public static record BlockDescription(Block block) implements FontDescription {}

// 一个简单的对象信息
public record BlockInfo(Block block) implements ObjectInfo {
    // 用于通过网络发送信息的编解码器
    public static final MapCodec<BlockInfo> MAP_CODEC = BuiltInRegistries.BLOCK.byNameCodec().fieldOf("block");

    @Override
    public FontDescription fontDescription() {
        // 要渲染的字体描述
        return new BlockDescription(this.block);
    }

    @Override
    public String description() {
        // 只是对象的文本描述
        return Objects.toString(BuiltInRegistries.BLOCK.getKey(this.block));
    }

    @Override
    public MapCodec<? extends ObjectInfo> codec() {
        return MAP_CODEC;
    }
}

// 创建用于渲染对象的 `GlyphSource` 和 `PlainTextRenderable`
public record BlockRenderable(...) implements PlainTextRenderable {
    // ...
}

public static GlyphSource create(Block block) {
    return new SingleSpriteSource(...);
}

ObjectInfo 也需要渲染到 ObjectInfos#ID_MAPPER

// 假设映射器已设为公开
ObjectInfos.ID_MAPPER.put("examplemod:block", BlockInfo.MAP_CODEC);

组件内容

组件内容现在也使用 id 映射器,而不是在类型上持有 id。这意味着创建自定义组件是通过以某种方式挂钩到 ComponentSerialization#bootstrap 并将您的 ComponentContents 实现的映射编解码器注册到映射器来完成的。

数据源

数据源也获得了与组件内容类似的处理,现在使用 id 映射器而不是在类型上持有 id。然后通过将您的 DataSource 的映射编解码器注册到 DataSources#ID_MAPPER 来注册数据源。请注意,映射器字段是私有的,因此您可能需要使用可用的解决方法。

  • com.mojang.blaze3d.font
    • GlyphInfo
      • bake -> UnbakedGlyph#bake,现在接受 UnbakedGlyph$Stitcher 而不是函数
        • 函数行为被 UnbakedGlyph$Stitcher#stitch 取代
      • $SpaceGlyphInfo -> GlyphInfo#simpleEmptyGlyph,不是一对一
      • $Stitched -> UnbakedGlyph,不是一对一
    • GlyphProvider#getGlyph 现在返回一个 UnbakedGlyph
    • SheetGlyphInfo -> GlyphBitmap
  • net.minecraft.client.gui
    • Font 不再接受函数和布尔值,而是接受 Font$Provider
      • random 现在是私有的
      • $GlyphVisitor
        • acceptGlyph 现在接受 TextRenderable 而不是 BakedGlyph$GlyphInstance
        • acceptEffect 现在只接受一个 TextRenderable
      • $PreparedTextBuilder#accept 现在有一个接受 BakedGlyph 而不是其码点的重载
      • $Provider - 一个简单的接口,用于根据其描述提供字形源,以及空字形。
    • GlyphSource - 一个接口,根据其码点持有烘焙的字形。
  • net.minecraft.client.gui.font
    • AtlasGlyphProvider - 基于纹理图集的字形提供者。
    • FontManager 现在接受 AtlasManagerPlayerSkinRenderCache
    • FontSet 现在接受 GlyphStitcher 而不是 TextureManager,并且不再接受名称
      • name 已移除
      • source - 根据是否只应看到非可疑字形,返回字形源。
      • getGlyphInfogetGlyph -> getGlyph,现在是包私有的,不是一对一
      • getRandomGlyph 现在接受 RandomSource 和一个码点而不是 GlyphInfo,返回一个 BakedGlyph
      • whiteGlyph 现在返回一个 EffectGlyph
      • $GlyphSource - 一个可以获取要烘焙的字形的源。
    • FontTexture#add 现在接受 GlyphInfoGlyphBitmap,返回一个 BakedSheetGlyph
    • GlyphStitcher - 一个从其字形信息创建 BakedGlyph 的类。
    • PlainTextRenderable - TextRenderable 的一个实现,确定如何渲染精灵。
    • PlayerGlyphProvider - 用于渲染玩家头部和帽子的字形提供者。
    • SingleSpriteSource - 一个只包含一个字形的字形源,例如一个纹理。
    • TextRenderable - 表示文本表示(如字体中的字形)如何渲染。
  • net.minecraft.client.gui.font.glyphs
    • BakedGlyph 现在是一个创建可渲染对象的接口
      • 其原始用途已移至 BakedSheetGlyph
    • EffectGlyph - 一个创建某个字形效果的可渲染对象的接口。
    • EmptyGlyph 现在实现 UnbakedGlyph 而不是继承 BakedGlyph
      • 构造函数接受字形的文本宽度。
    • SpecialGlyphs#bake 现在返回一个 BakedSheetGlyph
      • 此方法在技术上是新的。
  • net.minecraft.client.gui.font.providers
    • BitmapProvider$Glyph 现在实现 UnbakedGlyph 而不是 GlyphInfo$Stitched
    • UnihexProvider$Glyph 现在实现 UnbakedGlyph 而不是 GlyphInfo$Stitched
  • net.minecraft.client.gui.render.state
    • GlyphEffectRenderState 已移除
      • 使用 GlyphRenderState
    • GlyphRenderState 现在接受 TextRenderable 而不是 BakedGlyph$Instance
  • net.minecraft.network.chat
    • Component#object - 创建一个带有对象内容的可变组件。
    • ComponentContents#type -> codec,丢弃字符串 id
      • $Type 已移除
    • ComponentSerialization
      • createLegacyComponentMatcher 不再需要 StringRepresentable 泛型,而是使用带有 String 键的 id 映射器
      • $FuzzyCodec 现在接受一组映射编解码器而不是一个列表
    • FontDescription - 一个描述字体的标识符,通常作为位置或精灵。
    • Style 现在是 final
      • getFont 现在返回一个 FontDescription
      • withFont 现在接受 FontDescription 而不是 ResourceLocation
      • DEFAULT_FONT 已移除
  • net.minecraft.network.chat.contents
    • BlockDataSource -> .data.BlockDataSource
    • DataSource -> .data.DataSource
      • type -> codec,丢弃字符串 id
    • EntityDataSource -> .data.EntityDataSource
    • *Contents
      • CODEC -> MAP_CODEC
      • TYPE 已移除
    • ObjectContents - 可以作为组件一部分写入的任意内容,例如精灵。
    • StorageDataSource -> .data.StorageDataSource
  • net.minecraft.network.chat.contents.data.DataSources - 所有原版注册的数据源。
  • net.minecraft.network.chat.contents.objects
    • AtlasSprite - 纹理图集中精灵的对象信息。
    • ObjectInfo - 通过字形管线传递任意对象的引用相关信息。
    • ObjectInfos - 所有原版对象信息。
    • PlayerSprite - 玩家头部和帽子纹理的对象信息。

JSON-RPC 管理服务器

Minecraft 引入了通过 JSON-RPC websocket 远程管理专用服务器的支持。这可以通过 management-server-enabled 属性启用,默认情况下它在 localhost:25585 上监听服务器。整个系统不仅处理通过 JsonElement 发送的网络请求的构造,还处理每个请求使用的模式。然后可以通过 JsonRpcApiSchema 数据提供者生成这些模式。

系统支持两种类型的 RPC 方法:来自管理服务器的请求的 IncomingRpcMethod,以及通知或向管理服务器请求信息的 OutgoingRpcMethod。这两者都是静态注册表对象,但通常通过其关联的构建器构造和注册,而不是实现接口。

模式

顾名思义,Schema 是 JSON 对象的规范。它们以类似于 JsonElement 的方式构造。大多数构造为 Schema#record,其字段和类型通过 withField 填充,然后存储在 SchemaComponent 中,该组件将引用名称映射到模式。然后可以通过 asRefasArray 分别获取对象或数组实现。SchemaComponent 本身被注册到列表 Schema#SCHEMA_REGISTRY 以进行引用解析。

// 一个更改天气的 JSON 示例:
{
    "weather": "clear|rain|thunder",
    "duration": -1,
}

关联的模式组件如下所示:

public static final SchemaComponent WEATHER_SCHEMA = new SchemaComponent(
    // 引用名称
    // 虽然我们可以使用冒号,但需要按照 RFC 3986 定义的百分号编码
    "examplemod_weather",
    // 要使用的模式
    Schema.record()
        .withField("weather", Schema.ofEnum(List.of("clear", "rain", "thunder")))
        .withField("duration", Schema.INT_SCHEMA)
);

// 将模式注册到注册表
Schema.getSchemaRegistry().add(WEATHER_SCHEMA);

请注意,模式目前无法指定单个属性是否可选。

IncomingRpcMethod

IncomingRpcMethod 通过 method 构建器构造和注册。这些方法接受更新 Minecraft 服务器的处理函数、结果的编解码器,以及一个来自管理服务器的参数的可选编解码器。从那里,构建器包含用于发现服务以及如何执行方法的方法。$IncomingRpcMethodBuilder#responseparam 定义管理服务器发送的参数和响应。description 由发现服务用于模式。undiscoverable 默认隐藏路由。最后,notOnMainThread 告诉该方法它可以在主线程之外运行。一旦调用了所需的方法,就可以使用 buildregister 来构造对象,接受路由端点的命名空间和路径。

传入的方法接受 MinecraftApi 用于通过指定的“服务”与专用服务器通信,以及当前的 ClientInfo 连接。如果存在参数对象,它也接受该参数对象。

// 构造 dto 对象
public record WeatherDto(String weather, int duration) {
    public static final Codec<WeatherDto> CODEC = RecordCodecBuilder.create(
        instance -> instance.group(
            Codec.STRING.fieldOf("weather").forGetter(WeatherDto::weather),
            Codec.INT.fieldOf("duration").forGetter(WeatherDto::duration),
        )
        .apply(instance, WeatherDto::new)
    );

    // 创建传入方法处理程序
    public static WeatherDto handleWeather(MinecraftApi api, WeatherDto params, ClientInfo info) {
        // 注意,api 使服务器私有,因为它期望逻辑通过其中一个中间层服务处理。
        // 我们将假设 `server` 字段以某种方式被设为公开。
        if (params.weather().equals("clear")) {
            api.server.overworld().setWeatherParameters(params.duration(), 0, false, false);
        } else if (params.weather().equals("rain")) {
            api.server.overworld().setWeatherParameters(0, params.duration(), true, false);
        } else if (params.weather().equals("thunder")) {
            api.server.overworld().setWeatherParameters(0, params.duration(), true, true);
        }

        return params;
    }
}

// 构造并注册方法端点
IncomingRpcMethod.method(
    // 处理程序方法
    WeatherDto::handleWeather,
    // 参数的编解码器
    WeatherDto.CODEC,
    // 结果的编解码器
    WeatherDto.CODEC
)
    // 设置路由的描述
    .description("设置天气")
    // 参数
    .param(new ParamInfo(
        // 对象的名称
        "weather",
        // 模式
        WEATHER_SCHEMA.asRef()
    ))
    // 响应
    .response(new ResultInfo(
        // 对象的名称
        "weather",
        // 模式
        WEATHER_SCHEMA.asRef()
    ))
    // 构建并注册路由
    .register(
        BuiltInRegistries.INCOMING_RPC_METHOD,
        // 端点命名空间
        "examplemod",
        // 端点路径
        "weather/update"
    );

OutgoingRpcMethod

OutgoingRpcMethod 通过 notificationrequest 构建器构造和注册。通知通常只发送参数而不返回结果,而请求也提供结果。在任何一种情况下,它们都只接受参数或结果(如果存在)的编解码器。$OutgoingRpcMethod#responseparam 定义 Minecraft 服务器发送的参数和响应。description 由发现服务用于模式。一旦调用了所需的方法,就可以使用 register 来构造对象,接受路由端点的命名空间和路径,并将其包装在 Holder$Reference 中。

目前,原版仅通过 NotificationService 广播通知:一个用于特定方法操作(如玩家加入或更改游戏规则)的远程日志记录器。虽然有结果,但必须通过 Connection#sendRequest 读取并异步处理。

// 构造传出方法
// 由于 Minecraft 服务器将发送这些,我们需要持有该对象
public static final Holder.Reference<OutgoingRpcMethod.ParmeterlessNotification> SOMETHING_HAPPENED = OutgoingRpcMethod.notification()
        .description("某件事发生了!")
        .register("examplemod", "something");

// 发送通知,假设我们可以访问 `ManagementServer` managementServer
managementServer.forEachConnection(connection -> connection.sendNotification(SOMETHING_HAPPENED));
  • net.minecraft.SharedConstants#RPC_MANAGEMENT_SERVER_API_VERSION - JSON RPC 服务器管理的 API 版本。
  • net.minecraft.core.registries
    • BuiltInRegistriesRegistries
      • INCOMING_RPC_METHOD - 对 RPC 服务的查询的注册表。
      • OUTGOING_RPC_METHOD - 来自 RPC 服务的广播的注册表。
  • net.minecraft.server
    • MinecraftServer
      • notificationManager - 返回当前通知管理器。
      • onGameRuleChanged - 处理当前服务器的游戏规则更改时的情况。
      • getOperatorUserPermissionLevel -> operatorUserPermissionLevel
      • isLevelEnabled -> isAllowedToEnterPortal,不是一对一
      • setPvpAllowedGameRules#RULE_PVP 取代
      • setFlightAllowedDedicatedServerProperties#allowFlight 取代
      • isCommandBlockEnabled 不再是抽象的
      • isSpawnerBlockEnabled - 返回刷怪笼方块是否可以生成实体。
      • getPlayerIdleTimeout -> playerIdleTimeout
      • kickUnlistedPlayers 不再接受 CommandSourceStack
      • pauseWhileEmptySeconds -> pauseWhenEmptySeconds
      • getSpawnProtectionRadius -> DedicatedServer#spawnProtectionRadius
      • isUsingWhiteList - 处理为服务器启用白名单用户。
      • setAutoSaveisAutoSave - 处理服务器是否应每隔一段时间自动保存。
  • net.minecraft.server.dedicated
    • DedicatedServer 现在接受 LevelLoadListener 而不是 ChunkProgressListenerFactory
      • setAllowFlight - 设置玩家是否可以在服务器中飞行。
      • setDifficulty - 设置服务器的游戏难度。
      • viewDistancesetViewDistance - 处理服务器的视距(可渲染区块)。
      • simulationDistancesetSimulationDistance - 处理服务器的模拟距离(逻辑运行区块)。
      • setMaxPlayers - 设置可以加入服务器的最大玩家数。
      • setSpawnProtectionRadius - 设置应受重生保护保护的区块半径。
      • setRepliesToStatus - 设置游戏是否使用旧式查询处理程序。
      • setHidesOnlinePlayers - 设置是否应隐藏在线玩家不被其他玩家看到。
      • setOperatorUserPermissionLevel - 设置操作员的权限级别。
      • statusHeartbeatIntervalsetStatusHeartbeatInterval - 处理管理服务器将检查 Minecraft 服务器是否仍然存活的心跳间隔。
      • entityBroadcastRangePercentagesetEntityBroadcastRangePercentage - 处理实体跟踪的广播范围标量。
      • forceGameModesetForceGameMode - 处理强制所有用户的游戏模式。
      • gameModesetGameMode - 设置服务器的默认游戏模式。
      • setAcceptsTransfers - 设置服务器是否接受来自其他服务器的客户端转移。
      • setPauseWhenEmptySeconds - 设置当没有玩家时服务器应等待多少秒才停止Tick。
    • DedicatedServerProperties
      • pvpGameRules#RULE_PVP 取代
      • allowFlightmotdforceGameModeenforceWhitelistdifficultygameModespawnProtectionopPermissionLevelviewDistancesimulationDistanceenableStatushideOnlinePlayersentityBroadcastRangePercentagepauseWhenEmptySecondsacceptsTransfers 现在是可变属性
      • allowNetherGameRules#RULE_ALLOW_NETHER 取代
      • spawnMonstersGameRules#RULE_SPAWN_MONSTERS 取代
      • enabledCommandBlockGameRules#RULE_COMMAND_BLOCKS_ENABLED 取代
      • managementServerEnabled - 返回是否启用了管理服务器。
      • managementServerHost - 返回管理服务器通信的主机。
      • managementServerPort - 返回管理服务器通信的端口。
      • statusHeartbeatInterval - 返回管理服务器发送以确保 Minecraft 服务器仍然存活的心跳间隔。
      • MANAGEMENT_SERVER_TLS_ENABLED_KEYMANAGEMENT_SERVER_TLS_KEYSTORE_KEYMANAGEMENT_SERVER_TLS_KEYSTORE_PASSWORD_KEY - 用于与管理服务器通信的 TLS 密钥库设置。
      • managementServerSecret - 授权令牌密钥。
      • managementServerTlsEnabled - 是否应使用 TLS 作为通信协议。
      • managementServerTlsKeystore - 指定用于 TLS 密钥库的文件路径。
      • managementServerTlsKeystorePassword - 指定密钥库文件的密码。
    • Settings#getMutable - 获取设置键和默认值的可变属性。
  • net.minecraft.server.jsonrpc
    • Connection - 管理服务器发送的 json 元素的入站处理程序。
    • IncomingRpcMethod - 管理服务器发送的传入消息的定义和处理程序。
    • IncomingRpcMethods - 所有原版传入 RPC 处理程序。
    • JsonRPCErrors - 一个枚举,包含尝试读取、解析或执行方法时可能抛出的错误。
    • JsonRpcLogger - 一个用于 Minecraft 服务器执行的操作(无论是通信还是逻辑)的通用日志记录器。
    • JsonRpcNotificationService - 一个向所有连接的 Minecraft 服务器广播的通知服务。
    • JsonRPCUtils - 用于请求对象和错误的实用工具。
    • ManagementServer - 一个用于 Minecraft 服务器与管理服务器通信的基本 websocket 通信。
    • OutgoingRpcMethod - 对管理服务器的传出请求的定义和处理程序。
    • OutgoingRpcMethods - 所有原版传出 RPC 处理程序。
    • PendingRpcRequest - Minecraft 服务器向管理服务器发出的待处理请求。
  • net.minecraft.server.jsonrpc.api
    • MethodInfo - 定义由管理服务器处理的方法,无论是入站还是出站。
    • ParamInfo - 定义特定方法接受的参数。
    • PlayerDto - 表示玩家的数据传输对象。
    • ReferenceUtil - 用于创建本地引用 URI 的实用工具。
    • ResultInfo - 定义特定方法返回的响应。
    • Schema - 用于发现服务、参数和结果的 JSON 模式的实现。
    • SchemaComponent - 模式中某个组件的引用定义。
  • net.minecraft.server.jsonrpc.dataprovider.JsonRpcApiSchema - 一个从发现服务生成 JSON 模式的数据提供者。
  • net.minecraft.server.jsonrpc.internalapi
    • GameRules - 一个获取当前游戏规则值的 API。
    • MinecraftAllowListService - 一个处理来自管理服务器的关于允许列表的通信的 Minecraft 中间层。
    • MinecraftAllowListServiceImpl - 允许列表实现。
    • MinecraftApi - 一个处理所有与管理服务器通信的服务的 Minecraft API。
    • MinecraftBanListService - 一个处理来自管理服务器的关于禁令列表的通信的 Minecraft 中间层。
    • MinecraftBanListServiceImpl - 禁令列表实现。
    • MinecraftExecutorService - 一个提交任意 runnable 或 supplier 以在服务器上执行的 Minecraft 中间层。
    • MinecraftExecutorServiceImpl - 执行器实现。
    • MinecraftGameRuleService - 一个处理来自管理服务器的关于游戏规则的通信的 Minecraft 中间层。
    • MinecraftExecutorServiceImpl - 执行器实现。
    • MinecraftOperatorListService - 一个处理来自管理服务器的关于操作员命令的通信的 Minecraft 中间层。
    • MinecraftOperatorListServiceImpl - 操作员列表实现。
    • MinecraftPlayerListService - 一个处理来自管理服务器的关于玩家列表的通信的 Minecraft 中间层。
    • MinecraftPlayerListServiceImpl - 玩家列表实现。
    • MinecraftServerSettingsService - 一个处理来自管理服务器的关于服务器设置的通信的 Minecraft 中间层。
    • MinecraftServerSettingsServiceImpl - 服务器设置实现。
    • MinecraftServerStateService - 一个处理来自管理服务器的关于当前服务器状态和发送消息的通信的 Minecraft 中间层。
    • MinecraftServerStateServiceImpl - 服务器状态实现。
  • net.minecraft.server.jsonrpc.methods
    • AllowlistService - 一个处理来自管理服务器的关于允许列表的通信的服务。
    • BanlistService - 一个处理来自管理服务器的关于玩家禁令列表的通信的服务。
    • ClientInfo - 当前 Minecraft 服务器连接到管理服务器的标识符。
    • DiscoveryService - 一个显示管理服务器支持的所有服务的模式的服务。
    • EncodeJsonRpcException - 尝试编码 JSON 数据包时抛出的异常。
    • GameRulesService - 一个处理来自管理服务器的关于游戏规则的通信的服务。
    • IllegalMethodDefinitionException - 当提供的方法定义非法时抛出的异常。
    • InvalidParameterJsonRpcException - 当方法的参数无效时抛出的异常。
    • InvalidRequestJsonRpcException - 当请求无效时抛出的异常。
    • IpBanlistService - 一个处理来自管理服务器的关于 IP 禁令列表的通信的服务。
    • Message - 表示字面量或可翻译组件的数据传输对象。
    • MethodNotFoundJsonRpcException - 当发生 404 错误时抛出的异常,表示方法不存在。
    • OperatorService - 一个处理来自管理服务器的关于操作员命令的通信的服务。
    • PlayerService - 一个处理来自管理服务器的关于玩家列表的通信的服务。
    • RemoteRpcErrorException - 当管理服务器上出现问题时抛出的异常。
    • ServerSettingsService - 一个处理来自管理服务器的关于服务器设置的通信的服务。
    • ServerStateService - 一个处理来自管理服务器的关于当前服务器状态和发送消息的通信的服务。
  • net.minecraft.server.jsonrpc.security
    • AuthenticationHandler - 处理请求中认证令牌持有者的验证。
    • JsonRpcSslContextProvider - 为 TLS 通信提供密钥库上下文。
    • SecurityConfig - 处理密钥,从检查基本有效性到生成新密钥。
  • net.minecraft.server.jsonrpc.websocket
    • JsonToWebSocketEncoder - 一个用于 JSON 的消息到消息编码器。
    • WebSocketToJsonCodec - 一个用于 JSON 的消息到消息解码器。
  • net.minecraft.server.notifications
    • EmptyNotificationService - 一个什么都不做的通知服务。
    • NotificationManager - 一个用于处理多个通知服务的管理器。
    • NotificationService - 一个定义由监听器(如管理服务器)采取的预期操作的服务。
  • net.minecraft.server.players
    • BanListEntry
      • getReason 现在可以为 null
      • getReasonMessage - 返回禁令原因的可翻译组件。
    • IpBanList 现在接受 NotificationService
      • addremove - 处理列表中的条目。
    • PlayerList 现在接受 NotificationService 而不是最大玩家数
      • maxPlayers 已移除
      • op 现在有一个用于权限级别和绕过限制布尔值的重载
      • setUsingWhiteList -> MinecraftServer#setUsingWhiteList
      • getPlayer - 通过名称获取玩家。
    • ServerOpList 现在接受 NotificationService
      • addremove - 处理列表中的条目。
    • StoredUserEntry#getUser 现在是公开的
    • StoredUserList 现在接受 NotificationService
      • addremove 现在返回一个布尔值表示是否成功
      • remove(StoredUserEntry<K>) 已移除
      • clear - 清除所有存储的用户。
    • UserBanList 现在接受 NotificationService
      • addremove - 处理列表中的条目。
    • UserWhiteList 现在接受 NotificationService
      • addremove - 处理列表中的条目。

输入处理整合

输入处理以前传递原始值,每个值都在自己单独的参数中,由 GLFW 提供。然而,相当多的处理逻辑是冗余的,因为特定的键通常被检查,或者所有值都在从一个方法到下一个方法的烫手山芋游戏中传递。考虑到这一点,GuiEventListener 和其他调用中的输入处理程序现在通过事件对象处理。这些对象仍然包含 GLFW 传递的信息;然而,现在它们通过超类 InputWithModifiers 接口进行了许多常见检查。

有两种类型的事件:用于按键的 KeyEvent 和用于鼠标按下的 MouseButtonEvent。键、扫描码和修饰符被包装到 KeyEvent 中。按钮、修饰符和 XY 屏幕位置被包装到 MouseButtonEvent 中。因此,这通常是一个拖放替换,只需删除上述任何参数并用它们适当的事件替换。

按键映射类别

按键映射略有变化,不再接受原始字符串作为其类别,而是使用 KeyMapping$Category 记录,它本质上是一个命名空间的字符串。可以使用 KeyMapping$Category#register 创建类别;否则,每当映射作为比较器的一部分使用时,都会抛出错误。

public static final KeyMapping.Category EXAMPLE = KeyMapping.Category.register(ResourceLocation.withNamespaceAndPath("examplemod", "example"));

双击扩展

GuiEventListener#mouseClicked 现在接受一个布尔值,表示该点击是否实际上是双击。

// 对于某个 Screen 子类(或 AbstractWidget 或任何 GUI 对象渲染)

@Override
public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
    // ...
    return false;
}
  • com.mojang.blaze3d.platform.InputConstants
    • MOD_SHIFTMOD_ALTMOD_SUPERMOD_CAPS_LOCKMOD_NUM_LOCK - 用于转换键输入的修饰键。
    • KEY_LWINKEY_RWIN -> KEY_LSUPERKEY_RSUPER
    • getKey 现在接受 KeyEvent 而不是键和扫描码 int
    • isKeyDownsetupKeyboardCallbackssetupMouseCallbacksgrabOrReleaseMouseupdateRawMouseInput 现在接受 Window 而不是 long 句柄
  • net.minecraft.client
    • KeyboardHandler
      • keyPress 现在是私有的
      • setup 现在接受 Window 而不是 long 句柄
    • KeyMapping 现在接受 $Category 而不是 String
      • shouldSetOnIngameFocus - 返回键是否映射到键盘上的某个值。
      • restoreToggleStatesOnScreenClosed - 将切换键恢复到游戏内操作期间的状态。
      • key 现在是 protected
      • release 现在是 protected
      • CATEGORY_* -> $Category#*
        • 可以通过 $Category#id 获取键
        • 组件可通过 $Category#label 获得
      • getCategory 现在返回 $Category 而不是 String
      • matches 现在接受 KeyEvent 而不是键和扫描码 int
      • matchesMouse 现在接受 MouseButtonEvent 而不是按钮 int
    • Minecraft#ON_OSX -> InputQuirks#ON_OSX
    • MouseHandler#setup 现在接受 Window 而不是 long 句柄
    • ToggleKeyMapping 现在有一个接受输入类型的重载
      • 构造函数现在接受 KeyMapping$Category 而不是 String,以及一个 boolean 表示是否应恢复按键绑定的先前状态
  • net.minecraft.client.gui.components
    • AbstractButton#onPress 现在接受 InputWithModifiers
    • AbstractScrollArea#updateScrolling 现在接受 MouseButtonEvent 而不是按钮信息和 XY 位置
    • AbstractWidget
      • onClick 现在接受 MouseButtonEvent 而不是 XY 位置以及按钮是否被双击
      • onRelease 现在接受 MouseButtonEvent 而不是 XY 位置
      • onDrag 现在接受 MouseButtonEvent 而不是 XY 位置
      • isValidClickButton 现在接受 MouseButtonInfo 而不是按钮 int
    • CommandSuggestions
      • keyPressed 现在接受 KeyEvent 而不是键、扫描码、修饰符 int
      • mouseClicked 现在接受 MouseButtonEvent 而不是按钮信息和 XY 位置
      • $SuggestionsList
        • mouseClicked 不再接受按钮 int
        • keyPressed 现在接受 KeyEvent 而不是键、扫描码、修饰符 int
    • MultilineTextField#keyPressed 现在接受 KeyEvent 而不是键 int
  • net.minecraft.client.gui.components.events.GuiEventListener
    • DOUBLE_CLICK_THRESHOLD_MS -> MouseHandler#DOUBLE_CLICK_THRESHOLD_MS
    • mouseClicked 现在接受 MouseButtonEvent 而不是按钮信息和 XY 位置,以及按钮是否被双击
    • mouseReleased 现在接受 MouseButtonEvent 而不是按钮信息和 XY 位置
    • mouseDragged 现在接受 MouseButtonEvent 而不是按钮信息和 XY 位置
    • keyPressed 现在接受 KeyEvent 而不是键、扫描码、修饰符 int
    • keyReleased 现在接受 KeyEvent 而不是键、扫描码、修饰符 int
    • charTyped 现在接受 CharacterEvent 而不是码点 char 和修饰符 int
  • net.minecraft.client.gui.font.TextFieldHelper
    • charTyped 现在接受 CharacterEvent 而不是码点 char
    • keyPressed 现在接受 KeyEvent 而不是键 int
  • net.minecraft.client.gui.navigation.CommonInputs 类已移除
    • selected -> InputWithModifiers#isSelection
    • confirm -> InputWithModifiers#isConfirmation
  • net.minecraft.client.gui.screens.Screen
    • hasControlDown -> Minecraft#hasControlDownInputWithModifiers#hasControlDown
    • hasShiftDown -> Minecraft#hasShiftDownInputWithModifiers#hasShiftDown
    • hasAltDown -> Minecraft#hasAltDownInputWithModifiers#hasAltDown
    • isCut -> InputWithModifiers#isCut
    • isPaste -> InputWithModifiers#isPaste
    • isCopy -> InputWithModifiers#isCopy
    • isSelectAll -> InputWithModifiers#isSelectAll
  • net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
    • hasClickedOutside 不再接受按钮 int
    • checkHotbarKeyPressed 现在接受 KeyEvent 而不是键和修饰符 int
  • net.minecraft.client.gui.screens.options.controls.KeyBindsList$CategoryEntry 现在接受 KeyMapping$Category 而不是 Component
  • net.minecraft.client.gui.screens.recipebook
    • hasClickedOutside 不再接受按钮 int
    • RecipeBookPage#mouseClicked 现在接受 MouseButtonEvent 而不是按钮信息和 XY 位置,以及按钮是否被双击
  • net.minecraft.client.input
    • CharacterEvent - 某种输入交互生成一个码点,带有当前活动的修饰符。
    • InputQuirks - 处理输入时操作系统之间差异的实用工具。
    • InputWithModifiers - 定义一个带有当前活动修饰符的输入,以及一些常见的输入检查。
    • KeyEvent - 某种输入交互通过扫描码生成一个键,带有当前活动的修饰符。
    • MouseButtonEvent - 某种输入交互在 XY 位置生成一个按钮。
    • MouseButtonInfo - 某种输入交互生成一个带有当前活动修饰符的按钮。

Level#isClientSide 现在为 private

Level#isClientSide 字段现在是私有的,因此所有查询都必须使用方法版本:

// 对于某个 Level level
level.isClientSide();
  • net.minecraft.world.level.Level#isClientSide 字段现在是私有的

小幅迁移

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

物品拥有者

Minecraft 进一步将物品模型中的物品持有者抽象为其自己的接口:ItemOwner。一个 ItemOwner 由三件事定义:持有者所在的 level、持有者的 position,以及持有者表示朝向的 Y 旋转(以度为单位)。ItemOwner 在每个 Entity 上实现;然而,它们的位置可以通过使用 ItemOwner#offsetFromOwner 或创建 ItemOwner$OffsetFromOwner 来偏移。

目前,只有新的架子方块使用偏移拥有者,以便指南针在放置时不会随机旋转。

  • net.minecraft.client.renderer.entity.ItemRenderer#renderStatic 现在接受一个可选的 ItemOwner 而不是 LivingEntity
  • net.minecraft.client.renderer.item
    • ItemModel#update 现在接受 ItemOwner 而不是 LivingEntity
    • ItemModelResolver#updateForTopItemappendItemLayers 现在接受 ItemOwner 而不是 LivingEntity
  • net.minecraft.client.renderer.item.properties.numeric
    • NeedleDirectionHelper#getcalculate 现在接受 ItemOwner 而不是 LivingEntity
    • RangeSelectItemModelProperty#get 现在接受 ItemOwner 而不是 LivingEntity
    • Time$TimeSource#get 现在接受 ItemOwner 而不是 Entity
  • net.minecraft.world.entity
    • Entity 现在实现 ItemOwner
    • ItemOwner - 表示正在渲染的物品的拥有者。

容器使用者

由于 Minecraft 的这个新版本引入了铜傀儡(一种可以与库存交互的原版生物),可以使用容器的实体的概念已被抽象为其自己的接口:ContainerUserContainerUser 预计将在某个 LivingEntity 子类上实现。由于实际的库存逻辑在其他地方处理,ContainerUser 只有两个方法:hasContainerOpen,检查活体实体当前是否正在打开某个容器(例如,桶、箱子);以及 getContainerInteractionRange,确定实体可以与某个容器交互的半径(以方块为单位)。

  • net.minecraft.world.Container
    • startOpenstopOpen 现在接受 ContainerUser 而不是 Player
    • getEntitiesWithContainerOpen - 返回正在与此容器交互的 ContainerUser 列表。
  • net.minecraft.world.entity.ContainerUser - 通常是可以与容器交互并打开容器的实体。
  • net.minecraft.world.entity.player.Player 现在实现 ContainerUser
  • net.minecraft.world.level.block.entity.EnderChestBlockEntity#startOpenstopOpen 现在接受 ContainerUser 而不是 Player

名称和 ID

除非需要 GameProfile,否则 Minecraft 现在为每个玩家传递一个 NameAndId。顾名思义,NameAndId 包含玩家的 UUID 和名称,因为对于涉及玩家实体的大多数逻辑来说,这通常就是全部所需。

  • net.minecraft.commands.arguments.GameProfileArgument
    • getGameProfiles 现在返回 NameAndId 的集合
    • $Result#getNames 现在返回 NameAndId 的集合
  • net.minecraft.network.codec.ByteBufCodecs#PLAYER_NAME - 玩家名称的 16 字节字符串流编解码器。
  • net.minecraft.network.protocol.status.ServerStatus$Players#Sample 现在是一个 NameAndId 列表,而不是 GameProfile
  • net.minecraft.server
    • MinecraftServer
      • getProfilePermissions 现在接受 NameAndId 而不是 GameProfile
      • isSingleplayerOwner 现在接受 NameAndId 而不是 GameProfile
      • ANONYMOUS_PLAYER_PROFILE 现在是一个 NameAndId
    • Services 现在接受 UserNameToIdResolver 而不是 GameProfileCache,以及一个 ProfileResolver
  • net.minecraft.server.players
    • GameProfileCache -> UserNameToIdResolverCachedUserNameToIdResolver;不是一对一
      • getAsync 已移除
      • add(GameProfile) 已移除
    • NameAndId - 一个包含配置文件的 UUID 和名称的对象。
    • PlayerList
      • load -> loadPlayerData,不是一对一
      • canPlayerLogin 现在接受 NameAndId 而不是 GameProfile
      • disconnectAllPlayersWithProfile 现在接受 UUID 而不是 GameProfile
      • opdeop 现在接受 NameAndId 而不是 GameProfile
      • isWhiteListedisOp 现在接受 NameAndId 而不是 GameProfile
      • canBypassPlayerLimit 现在接受 NameAndId 而不是 GameProfile
    • ServerOpList 现在接受 NameAndId 作为其第一个泛型
      • canBypassPlayerLimit 现在接受 NameAndId 而不是 GameProfile
    • ServerOpListEntry 现在接受 NameAndId 作为其泛型和构造函数
    • UserBanList 现在接受 NameAndId 作为其第一个泛型
      • isBanned 现在接受 NameAndId 而不是 GameProfile
    • UserBanListEntry 现在接受 NameAndId 作为其泛型和构造函数
    • UserWhiteList 现在接受 NameAndId 作为其第一个泛型
      • isWhiteListed 现在接受 NameAndId 而不是 GameProfile
    • UserWhiteListEntry 现在接受 NameAndId 作为其泛型和构造函数
  • net.minecraft.world.entity.player.Player#nameAndId - 返回玩家的名称和 ID。
  • net.minecraft.world.level.storage.PlayerDataStorage#load(Player, ProblemReporter) -> load(NameAndId),返回一个 Optional<CompoundTag>

类型化实体数据

用于存储方块和实体数据的数据组件已从使用 CustomData 更改为类型安全的变体 TypedEntityDataTypedEntityDataCustomData 几乎相同,存储一个 CompoundTag,不同之处在于它由某个 IdType 泛型(如 EntityTypeBlockEntityType)表示。CustomData 中与方块实体和实体相关的所有方法都已移至 TypedEntityData

刷怪蛋使用 TypedEntityData 来存储它将生成的 EntityType。生成的逻辑仍然与 SpawnEggItem 子类绑定。

  • net.minecraft.core.component.DataComponents#ENTITY_DATABLOCK_ENTITY_DATA 现在是带有 EntityTypeBlockEntityType id 的 TypeEntityData
  • net.minecraft.world.entity.EntityType#updateCustomEntityTag 现在接受 TypedEntityData 而不是 CustomData
  • net.minecraft.world.item.Item$Properties#spawnEgg - 添加带有实体类型的 ENTITY_DATA 组件。
  • net.minecraft.world.item.component
    • CustomData
      • CODEC_WITH_ID 已移除
      • COMPOUND_TAG_CODEC - 用于扁平复合标签的编解码器。
      • parseEntityIdparseEntityType 已移除
      • loadInto -> TypedEntityData#loadInto
      • updatereadsize 已移除
      • contains -> TypedEntityData#contains
      • getUnsafe -> TypedEntityData#getUnsafe
    • TypedEntityData - 一个提供类型安全标识符的自定义数据。
  • net.minecraft.world.level.Spawner#appendHoverTextgetSpawnEntityDisplayName 现在接受 TypedEntityData 而不是 CustomData
  • net.minecraft.world.level.block.entity.BeehiveBlockEntity$Occupant#entityData 现在是一个 TypedEntityData

重载监听器共享状态

PreparableReloadListener 现在可以选择通过使用 PreparableReloadListener#prepareSharedState 在其他重载监听器之间共享数据。prepareSharedState 在调用 reload 之前在主线程上运行,可以将任意值存储到某个 $SharedKey,基本上作为一个字典查找。然后,一旦调用 reload,就可以通过键获取并使用存储的数据。通常,使用的共享值是某种 CompletableFuture 并在内部连接。

public class FirstExampleListener implements PreparableReloadListener {

    // 创建要写入共享数据的键
    public static final PreparableReloadListener.StateKey<CompletableFuture<Void>> EXAMPLE = new PreparableReloadListener.StateKey<>();

    @Override
    public void prepareSharedState(PreparableReloadListener.SharedState state) {
        // 将数据添加到共享状态
        state.set(EXAMPLE, CompletableFuture.allOf());
    }

    @Override
    public CompletableFuture<Void> reload(PreparableReloadListener.SharedState state, Executor tasksExecutor, PreparableReloadListener.PreparationBarrier barrier, Executor reloadExecutor) {
        // 使用共享状态
        var example = state.get(EXAMPLE);
    }
}


public class SecondExampleListener implements PreparableReloadListener {

    @Override
    public CompletableFuture<Void> reload(PreparableReloadListener.SharedState state, Executor tasksExecutor, PreparableReloadListener.PreparationBarrier barrier, Executor reloadExecutor) {
        // 在不同的监听器中使用共享状态
        var example = state.get(FirstExampleListener.EXAMPLE);
    }
}
  • net.minecraft.server.packs.resources
    • PreparableReloadListener
      • reload 现在接受 PreparableReloadListener$SharedState 而不是 ResourceManager
      • prepareSharedState - 在重载监听器重新加载之前调用的方法,用于在重载监听器之间共享数据。
      • $SharedState - 一个通用字典,可以在重载监听器之间提供资源,尽管它们通常应采用 CompletableFuture 的形式。
      • $StateKey - 共享状态的一个键。
    • SimpleReloadInstance$StateFactory#create 现在接受 PreparableReloadListener$SharedState 而不是 ResourceManager

加载票标志

TicketType 已更新为接受一个表示加载票属性位掩码的标志,而不是布尔值和枚举。

// 这需要注册到 BuiltInRegistries#TICKET_TYPE
public static final TicketType EXAMPLE = new TicketType(
    20L, // 加载票超时并被移除前的刻数,如果加载票永不过时则设置为 0
    // 要设置的位标志,请参阅下面的新标志的替换和说明
    TicketType.FLAG_SIMULATION | TicketType.FLAG_LOADING
);
  • net.minecraft.server.level.TicketType 现在接受一个标志位掩码,而不是布尔值和加载票用途
    • FLAG_PERSISTpersist 取代了布尔值
    • FLAG_LOADING 取代了 $TicketUse#LOADING
    • FLAG_SIMULATION 取代了 $TicketUse#SIMULATION
    • FLAG_KEEP_DIMENSION_ACTIVEshouldKeepDimensionActive - 设置后,防止等级卸载。
    • FLAG_CAN_EXPIRE_IF_UNLOADEDcanExpireIfUnloaded - 设置后,如果区块被卸载,加载票将过期。
    • START -> PLAYER_SPAWNSPAWN_SEARCH
    • $TicketUse 类已移除
  • net.minecraft.world.level.TicketStorage
    • shouldKeepDimensionActive - 检查存储中是否有任何加载票设置了维度活动标志。
    • removeTicketIf 现在接受 $TicketPredicate 而不是 BiPredicate
    • $TicketPredicate - 测试给定区块位置的加载票。

重生数据

重生逻辑已被整合到一个称为 LevelData$RespawnData 的单一对象中。重生数据保存全局位置(等级键和方块位置)以及实体的旋转。所有对原始角度和位置方法的调用已被 Level#setRespawnDatagetRespawnData 取代,后者委托给 MinecraftServer 并最终委托给等级数据。

  • net.minecraft.client.multiplayer.ClientLevel#setDefaultSpawnPos -> Level#setRespawnData
  • net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket 现在是一个记录
    • 参数已被一个 LevelData$RespawnData 对象取代
  • net.minecraft.server.MinecraftServer
    • findRespawnDimension - 获取玩家应重生的默认 ServerLevel
    • setRespawnData - 设置默认重生位置。
    • getRespawnData - 获取默认重生位置。
  • net.minecraft.server.level
    • ServerLevel#setDefaultSpawnPos -> Level#setRespawnData
    • ServerPlayer$RespawnConfig 现在接受 LevelData$RespawnData 而不是维度、位置和角度
      • 字段仍然可以从重生数据访问
  • net.minecraft.world.level.Level#getSharedSpawnPosgetSharedSpawnAngle -> getRespawnDatagetWorldBorderAdjustedRespawnData,不是一对一
  • net.minecraft.world.level.storage
    • LevelData
      • getSpawnPosgetSpawnAngle -> getRespawnData,不是一对一
      • $RespawnData - 定义默认重生玩家的全局位置、偏航角和俯仰角。
    • WritableLevelData#setSpawn 现在只接受 LevelData$RespawnData

“在架子上”变换

模型现在有一个新的变换,用于确定物品如何放置在架子上,称为 on_shelf

  • net.minecraft.client.renderer.block.model.ItemTransforms#fixedFromBottom - 一个期望物品放置在某个固定底部(如架子)上的变换。
  • net.minecraft.world.item.ItemDisplayContext#ON_SHELF - 当物品被放置在架子上时。

客户端资源拆分

ClientAsset 已被重写,以更好地指定资源引用的内容。目前,原版添加了 ClientAsset$Texture 来指定资源是一个纹理,它进一步子类化为用于从互联网下载的纹理的 $DownloadedTexture,以及用于从磁盘上某些现有资源访问的纹理的 $ResourceTexture

  • net.minecraft.advancements.DisplayInfo 现在接受一个可选的 ClientAsset$ResourceTexture 作为背景,而不是 ClientAsset
  • net.miencraft.client.renderer.texture.SkinTextureDownloader#downloadAndRegisterSkin 现在返回 ClientAsset$Texture 的 future,而不是 ResourceLocation
  • net.minecraft.client.resources
    • PlayerSkin -> net.minecraft.world.entity.player.PlayerSkin
      • 构造函数现在接受 ClientAsset$Texture 而不是 ResourceLocationString
      • texturetextureUrl -> body
      • capeTexture -> cape
      • elytraTexture -> elytra
      • insecure - 构造一个 insecure 设置为 false 的 PlayerSkin
      • with - 从其 $Patch 构建 PlayerSkin
      • $Patch - 一个打包对象,表示在其他文件或通过网络发送时的皮肤。
    • SkinManager$TextureCache#getOrLoad 现在返回 ClientAsset$Texture 的 future,而不是 ResourceLocation
  • net.minecraft.core.ClientAsset 现在是一个接口而不是记录
    • 原始实现移至 $ResourceTexture
    • id 仍然作为一个方法存在
    • texturePath -> $Texture#texturePath
    • CODECDEFAULT_FIELD_CODECSTREAM_CODEC -> $ResourceTexture#*
    • $DownloadedTexture - 从互联网下载的纹理。
    • $Texture - 定义一个纹理的客户端资源。
  • net.minecraft.world.entity.animal.CatVariant#assetInfo 现在接受 ClientAsset$ResourceTexture 而不是 ClientAsset
  • net.minecraft.world.entity.animal.frog.FrogVariant#assetInfo 现在接受 ClientAsset$ResourceTexture 而不是 ClientAsset
  • net.minecraft.world.entity.animal.wolf.WolfVariant$AssetInfo#* 现在接受 ClientAsset$ResourceTexture 而不是 ClientAsset
  • net.minecraft.world.entity.variant.ModelAndTexture#asset 现在接受 ClientAsset$ResourceTexture 而不是 ClientAsset

光标类型

屏幕上的当前光标现在可以通过 GUI 中的 GuiGraphics#requestCursor 或任何其他地方的 Window#selectCursor 更改为本机 CursorType,通过 GLFW#glfwCreateStandardCursor。注意 Window#setAllowCursorChanges 必须为 true,这可以通过选项菜单设置。

  • com.mojang.blaze3d.platform.Window
    • setAllowCursorChanges - 设置光标是否可以更改为不同的标准形状。
    • selectCursor - 将当前光标设置为指定类型。
  • com.mojang.blaze3d.platform.cursor
    • CursorType - GLFW 标准光标形状的定义。
      • createStandardCursor - 从其形状、名称和后备创建标准光标。
    • CursorTypes - Blaze3d 的光标类型。
  • net.minecraft.client.Options#allowCursorChanges - 设置光标是否可以更改为不同的标准形状。
  • net.minecraft.client.gui.GuiGraphics
    • requestCursor - 请求光标提交以进行渲染。
    • applyCursor - 应用光标更改以进行渲染。

新标签

  • minecraft:block
    • wooden_shelves
    • copper_chests
    • lightning_rods
    • copper
    • copper_golem_statues
    • incorrect_for_copper_tool
    • chains
    • lanterns
    • bars
  • minecraft:entity_types
    • cannot_be_pushed_onto_boats
    • accepts_iron_golem_gift
    • candidate_for_iron_golem_gift
  • minecraft:item
    • wooden_shelves
    • copper_chests
    • lightning_rods
    • copper
    • copper_golem_statues
    • copper_tool_materials
    • repairs_copper_armor
    • chains
    • lanterns
    • bars
    • shearable_from_copper_golem

新增列表

  • com.mojang.blaze3d.GraphicsWorkarounds#isGlOnDx12 - 返回渲染器是否使用 DirectX 12。
  • com.mojang.blaze3d.opengl.GlStateManager#incrementTrackedBuffers - 增加游戏使用的缓冲区数量。
  • com.mojang.blaze3d.systems.TimerQuery#isRecording - 返回是否有当前活动的查询。
  • net.minecraft.SharedConstants#RESOURCE_PACK_FORMAT_MINORDATA_PACK_FORMAT_MINOR - 资源包版本的次要组件。
  • net.minecraft.advancements.critereon.MinMaxBounds
    • bounds - 返回值的边界。
    • $FloatDegrees - 表示某个角度的浮点数的边界。
  • net.minecraft.client
    • Minecraft
      • isOfflineDevelopedMode - 返回游戏是否处于离线开发者模式。
      • canSwitchGameMode - 玩家实体是否存在并具有游戏模式。
      • playerSkinRenderCache - 返回持有玩家渲染纹理的缓存。
      • canInterruptScreen - 当前屏幕是否可以被另一个屏幕关闭。
      • packetProcessor - 返回调度和处理数据包的处理器。
    • Options
      • invertMouseX - 当为 true 时,反转 X 轴鼠标移动。
      • toggleAttack - 当为 true 时,将攻击键设置为可切换。
      • toggleUse - 当为 true 时,将使用键设置为可切换。
      • sprintWindow - 双击前进键激活疾跑的时间窗口(以刻为单位)。
      • saveChatDrafts - 返回如果输入框关闭,正在聊天中键入的消息是否应保留。
      • keySpectatorHotbar - 调出旁观者快捷栏菜单的键。
    • ToggleKeyMapping#shouldRestoreStateOnScreenClosed - 屏幕关闭后是否应恢复先前的切换状态。
  • net.minecraft.client.animation.definitions.CopperGolemAnimation - 铜傀儡的动画。
  • net.minecraft.client.data.models.BlockModelGenerators
    • and - 将给定的条件进行 AND 运算。
    • createShelf - 从基础纹理和粒子纹理创建一个架子方块状态。
    • addShelfPart - 为架子的所有状态添加一个模型的变体。
    • forEachHorizontalDirection - 对一对方向和旋转执行操作。
    • shelfCondition - 基于架子的状态构造一个条件。
    • createCopperGolemStatues - 创建所有铜傀儡雕像。
    • createCopperGolemStatue - 为提供的方块、铜块和锈蚀状态创建一个铜傀儡雕像。
    • createCopperChests - 创建所有铜箱子。
    • createCopperLantern - 创建一个灯笼和悬挂式灯笼。
    • createCopperChain - 创建一个链。
    • createCopperChainItem - 创建一个链物品模型。
  • net.minecraft.client.data.models.model
    • ModelTemplate
      • SHELF_* - 用于将架子构建为多部分的模型模板。
      • LIGHTNING_ROD - 避雷针的模型模板。
      • CHAIN - 链的模型模板。
      • BARS_* - 用于构建类似栏杆方块的模型模板。
    • TexturedModel#CHAIN - 链的模型提供者。
    • TextureMapping#bars - 类似栏杆方块的纹理映射。
    • TextureSlot#BARS - 对 #bars 纹理的引用。
  • net.minecraft.client.gui
    • Gui#renderDeferredSubtitles - 在屏幕上渲染字幕。
    • GuiGraphics#getSprite - 从其材质获取 TextureAtlasSprite
  • net.minecraft.client.gui.components
    • AbstractScrollArea#isOverScrollbar - 返回当前光标位置是否在滚动条上。
    • AbstractSelectionList
      • sort - 对列表中的条目进行排序。
      • swap - 交换列表中两个条目的位置
      • clearEntriesExcept - 移除所有与提供的元素不匹配的条目。
      • getNextY - 返回渲染滚动组件的 Y 分量。
      • entriesCanBeSelected - 列表中的条目是否可以被选择。
      • scrollToEntry - 滚动条,使选中的条目显示在屏幕上。
      • removeEntries - 移除提供的列表中的所有条目。
      • $Entry
        • set* - 设置组件大小。
        • getContent* - 获取内容大小和位置。
    • ChatComponent
      • saveAsDraftdiscardDraft - 处理聊天框中的草稿消息。
      • createScreenopenScreenpreserveCurrentChatScreenrestoreChatScreen - 根据草稿聊天选项处理屏幕行为。
      • $ChatMethod - 定义聊天的消息类型。
      • $Draft - 定义聊天框中的草稿消息。
    • EditBox
      • DEFAULT_HINT_STYLE - 默认提示的样式。
      • SEARCH_HINT_STYLE - 可搜索提示的样式,例如配方书中的提示。
      • $TextFormatter - 用于格式化框中字符串的接口。
    • FittingMultiLineTextWidget#minimizeHeight - 将小部件的高度设置为内部高度和内边距。
    • FocusableTextWidget$BackgroundFill - 一个枚举,表示何时应填充背景。
    • ItemDisplayWidget#renderTooltip - 提交要渲染的工具提示。
    • MultiLineLabel$Align - 处理标签的对齐方式。
    • MultilineTextField#selectWordAtCursor - 选择光标当前所在的单词。
    • SpriteIconButton$Builder#withTooltip - 设置显示消息的工具提示。
    • StringWidget
      • setMaxWidth - 设置字符串的最大宽度以及如何处理多余的宽度。
      • $TextOverflow - 如果文本长于最大宽度,则采取的操作。
  • net.minecraft.client.gui.components.events.GuiEventListener#shouldTakeFocusAfterInteraction - 当为 true 时,在点击时将元素设置为焦点。
  • net.minecraft.client.gui.screens
    • ChatScreen
      • isDraft - 框中是否有未发送的消息。
      • exitReason - 聊天屏幕被关闭的原因。
      • shouldDiscardDraft - 是否应丢弃当前的草稿消息。
      • $ChatConstructor - 基于草稿状态的聊天屏幕的构造函数。
      • $ExitReason - 聊天屏幕被关闭的原因。
    • FaviconTexture#isClosed - 返回纹理是否已关闭。
    • LevelLoadingScreen
      • update - 更新当前加载跟踪器和原因。
      • $Reason - 更改等级加载屏幕的原因。
    • Overlay#tick - Tick覆盖层。
    • Screen
      • panoramaShouldSpin - 返回渲染的全景图是否应旋转其相机。
      • setNarrationSuppressTime - 设置旁白应被抑制到什么时间。
      • isInGameUi - 返回屏幕是否在游戏进行中(而不是暂停菜单)打开。
      • isAllowedInPortal - 此屏幕是否可以在传送门过渡效果期间打开。
      • canInterruptWithAnotherScreen - 此屏幕是否可以被另一个屏幕关闭,默认为“按 Esc 关闭”屏幕。
  • net.minecraft.client.gui.screens.inventory.AbstractCommandBlockScreen#addExtraControls - 向命令方块屏幕添加任何额外的小部件。
  • net.minecraft.client.gui.screens.multiplayer
    • CodeOfConductScreen - 一个显示服务器的行为准则文本的屏幕。
    • ServerSelectionList$Entry
      • matches - 返回提供的条目是否与此条目匹配。
      • join - 处理客户端如何加入服务器条目。
  • net.minecraft.client.gui.screens.reporting.ChatSelectionScreen$ChatSelectionList#ITEM_HEIGHT - 列表中每个条目的高度。
  • net.minecraft.client.gui.screens.worldselection.WorldSelectionList
    • returnToScreen - 重新加载世界列表后返回上一个屏幕。
    • $Builder - 创建一个新的 WorldSelectionList
    • $Entry#getLevelSummary - 返回所选世界的摘要。
    • $EntryType - 一个枚举,表示条目的世界类型。
    • $NoWorldsEntry - 一个没有世界可供选择的条目。
  • net.minecraft.client.main.GameConfig$GameData#offlineDeveloperMode - 游戏是否离线并用于开发。
  • net.minecraft.client.multiplayer
    • ClientCommonPacketListenerImpl
      • seenPlayers - 该玩家看到的所有玩家,无论他们当前是否在线。
      • seenInsecureChatWarning - 玩家是否已看到不安全聊天警告。
      • $CommonDialogAccess - 客户端网络使用的对话框访问。
    • ClientConfigurationPacketListenerImpl#DISCONNECTED_MESSAGE - 因不接受行为准则而断开连接时显示的消息。
    • ClientExplosionTracker - 跟踪客户端上发生的爆炸,专门用于处理粒子。
    • ClientLevel
      • endFlashState - 处理末地中出现的闪光状态。
      • trackExplosionEffects - 跟踪爆炸以处理其粒子。
    • ClientPacketListener
      • getSeenPlayers - 返回该玩家看到的所有玩家。
      • getPlayerInfoIgnoreCase - 获取提供的配置文件名称的玩家信息。
  • net.minecraft.client.player.LocalPlayerResolver - 本地玩家的配置文件解析器。
  • net.minecraft.client.resources.WaypointStyle#ICON_LOCATION_PREFIX - 路径点图标的前缀。
  • net.minecraft.client.server.IntegratedServer#MAX_PLAYERS - 本地托管服务器允许的最大玩家数。
  • net.minecraft.client.sounds
    • DirectionalSoundInstance - 一个根据相机方向改变位置的声音。
    • SoundEngineExecutor#startUp - 创建运行引擎的线程。
    • SoundPreviewHandler - 一个用于预览某个事件在给定设置下听起来如何的实用工具。
  • net.minecraft.core
    • BlockPos#betweenCornersInDirection - 一个可迭代对象,按向量提供的方向遍历提供的边界。
    • Direction#axisStepOrder - 返回应检查给定向量的方向列表。
  • net.minecraft.core.particles.ExplosionParticleInfo - 用作爆炸一部分的粒子。
  • net.minecraft.data.loot.BlockLootSubProvider#createCopperGolemStatueBlock - 铜傀儡雕像的战利品表。
  • net.minecraft.data.loot.packs
    • VanillaBlockInteractLoot - 来自实体交互的原版方块战利品的子提供者。
    • VanillaChargedCreeperExplosionLoot - 来自闪电苦力怕爆炸的原版实体战利品的子提供者。
    • VanillaEntityInteractLoot - 来自实体交互的原版实体战利品的子提供者。
  • net.minecraft.data.recipes.RecipeProvider#shelf - 从一个物品构造一个架子配方。
  • net.minecraft.data.worldgen.BiomeDefaultFeatures#addNearWaterVegetation - 在水体附近添加植被。
  • net.minecraft.gametest.framework.GameTestHelper#getTestDirection - 获取测试面向的方向。
  • net.minecraft.network
    • FriendlyByteBuf#readLpVec3writeLpVec3 - 处理同步压缩的 Vec3
    • LpVec3 - 一个 vec3 网络处理程序,将向量压缩和解压缩为最多两个字节和两个整数。
    • PacketProcessor - 用于调度和处理数据包的处理器。
  • net.minecraft.network.chat.CommonComponents#GUI_COPY_TO_CLIPBOARD - 将聊天复制到剪贴板时显示的消息。
  • net.minecraft.network.protocol.configuration
    • ClientboundCodeOfConductPacket - 一个将服务器的行为准则发送给加入客户端的数据包。
    • ClientConfigurationPacketListener#handleCodeOfConduct - 处理从服务器发送的行为准则。
    • ServerboundAcceptCodeOfConductPacket - 一个发送客户端从服务器读取行为准则的接受响应的数据包。
    • ServerConfigurationPacketListener#handleAcceptCodeOfConduct - 处理来自客户端的行为准则接受。
  • net.minecraft.network.syncher.EntityDataSerializers
    • WEATHERING_COPPER_STATE - 傀儡上铜的风化状态。
    • COPPER_GOLEM_STATE - 铜傀儡的逻辑状态。
    • RESOLVABLE_PROFILE - 实体的可解析配置文件。
  • net.minecraft.server.MinecraftServer
    • selectLevelLoadFocusPos - 返回服务器的加载中心位置,通常是共享重生位置。
    • getLevelLoadListener - 返回用于跟踪等级加载的监听器。
    • getCodeOfConducts - 返回文件名到其行为准则文本的映射。
    • enforceGameTypeForPlayers - 设置所有玩家的游戏类型。
    • packetProcessor - 返回服务器的数据包处理器。
  • net.minecraft.server.commands.FetchProfileCommand - 获取给定用户的配置文件。
  • net.minecraft.server.dedicated.DedicatedServerProperties#codeOfConduct - 服务器是否有行为准则。
  • net.minecraft.server.level
    • ChunkLoadCounter - 在等级加载或玩家生成时跟踪区块加载。
    • ChunkMap
      • getLatestStatus - 返回给定区块位置的最新状态。
      • isTrackedByAnyPlayer - 检查实体是否被任何玩家跟踪。
      • forEachEntityTrackedBy - 遍历给定玩家跟踪的每个实体。
      • forEachReadyToSendChunk - 遍历每个准备好发送给客户端的区块。
    • ServerChunkCache
      • hasActiveTickets - 检查当前等级是否有任何保持其加载的活动加载票。
      • addTicketAndLoadWithRadius - 向某个位置添加加载票,并加载该位置及其半径内的区块。
    • ServerEntity$Synchronizer - 处理向跟踪实体发送数据包。
    • ServerLevel#isSpawningMonsters - 返回服务器是否可以生成怪物。
    • ServerPlayer$SavedPosition - 保存玩家在磁盘上的当前位置。
  • net.minecraft.server.level.progress.ChunkLoadStatusView - 加载区块的状态视图。
  • net.minecraft.server.network.ConfigurationTask#tick - 每刻调用该任务,直到返回 true,然后完成任务。
  • net.minecraft.server.network.config
    • PrepareSpawnTask - 一个查找玩家生成点的配置任务。
    • ServerCodeOfConductConfigurationTask - 一个将行为准则发送给客户端的配置任务。
  • net.minecraft.server.packs.OverlayMetadataSection
    • codecForPackType - 根据资源包类型为部分构造一个编解码器。
    • forPackType - 从资源包类型获取元数据部分类型。
  • net.minecraft.server.packs.metadata.MetadataSectionType#withValue$WithValue - 持有元数据部分及其提供的值。
  • net.minecraft.server.packs.metadata.pack
    • PackFormat - 表示资源包的主要和次要修订版本。
    • PackMetadataSection#forPackType - 从资源包类型获取元数据部分类型。
  • net.minecraft.server.packs.repository.PackCompatibility#UNKNOWN - 资源包与游戏的兼容性未知,因为主要版本设置为最大整数值。
  • net.minecraft.server.packs.resources.ResourceMetadata#getTypedSectiongetTypedSections - 获取提供的类型的元数据部分。
  • net.minecraft.server.players.ProfileResolver - 从其名称或 UUID 解析游戏配置文件。
  • net.minecraft.util
    • ExtraCodecs
      • gameProfileCodec - 给定 UUID 编解码器,为 GameProfile 创建一个编解码器。
      • $LateBoundIdMapper#values - 返回映射器内的值集合。
    • InclusiveRange#map - 将一个泛型的范围映射到另一个泛型。
    • Mth#ceilLong - 返回向上取整到最近长整型的双精度值。
  • net.minecraft.util.random
    • Weighted#streamCodec - 为加权条目构造一个流编解码器。
    • WeightedList#streamCodec - 为加权列表构造一个流编解码器。
  • net.minecraft.util.thread.BlockableEventLoop#shouldRunAllTasks - 返回是否有任何阻塞的任务。
  • net.minecraft.world.Nameable#getPlainTextName - 返回名称组件的字符串。
  • net.minecraft.world.entity
    • Avatar - 一个构成玩家基础的实体。
    • EntityReference
      • getEntity - 根据类型类和等级返回实体。
      • 静态 getEntitygetLivingEntitygetPlayer - 根据其 EntityReference 和等级返回实体。
    • EntityType
      • MANNEQUIN - 人体模型实体类型。
      • STREAM_CODEC - 实体类型的流编解码器。
      • $Builder#notInPeaceful - 设置实体不在和平模式下生成。
    • Entity
      • canInteractWithLevel - 实体是否可以与当前等级交互。
      • isInShallowWater - 返回玩家是否在水中但未在水下。
      • getAvailableSpaceBelow - 返回实体与碰撞体之间在 Y 方向上的空间量,按给定值偏移。
      • collectAllColliders - 返回所有实体碰撞。
    • InsideBlockEffectType#CLEAR_FREEZE - 一个清除冰冻刻数的方块内效果。
    • LivingEntity
      • dropFromEntityInteractLootTable - 从实体交互的战利品表中掉落战利品。
      • shouldTakeDrowningDamage - 实体是否应受到溺水伤害。
    • Mob#WEARING_ARMOR_UPGRADE_MATERIAL_CHANCEWEARING_ARMOR_UPGRADE_MATERIAL_ATTEMPTS - 盔甲材料升级的常量。
    • PositionMoveRotation#withRotation - 使用提供的 XY 旋转创建一个新对象。
    • Relative
      • rotation - 从 XY 布尔值获取相对旋转的集合。
      • position - 从 XYZ 布尔值获取相对位置的集合。
      • direction - 从 XYZ 布尔值获取相对增量的集合。
  • net.minecraft.world.entity.ai.Brain#isBrainDead - 返回大脑是否没有任何记忆、传感器或行为。
  • net.minecraft.world.entity.ai.behavior.TransportItemsBetweenContainers - 一个实体将在访问过的容器之间移动物品的行为。
  • net.minecraft.world.entity.ai.memory.MemoryModuleType
    • VISITED_BLOCK_POSITIONS - 访问过的重要方块位置。
    • TRANSPORT_ITEMS_COOLDOWN_TICKS - 在运输物品之前等待多少刻。
    • UNREACHABLE_TRANSPORT_BLOCK_POSITIONS - 保存一个无法到达的位置列表。
  • net.minecraft.world.entity.ai.navigation.GroundPathNavigation#setCanPathToTargetsBelowSurface - 设置实体是否可以将起始位置下方非空气方块下方的其他实体作为目标。
  • net.minecraft.world.entity.animal.coppergolem
    • CopperGolem - 铜傀儡实体。
    • CopperGolemAi - 铜傀儡的大脑逻辑。
    • CopperGolemOxidationLevel - 一个记录,保存给定氧化等级的源事件和纹理。
    • CopperGolemOxidationLevels - 所有原版氧化等级。
    • CopperGolemState - 铜傀儡所处的当前逻辑状态。
  • net.minecraft.world.entity.decoration
    • HangingEntity#canCoexist - 是否有任何其他悬挂实体与此实体位于同一位置。默认情况下,确保实体不是相同的实体类型且不面向相同的方向。
    • Mannequin - 一个没有连接玩家的人体模型。
  • net.minecraft.world.entity.player
    • Player
      • isMobilityRestricted - 返回玩家是否有失明效果。
      • handleShoulderEntities - 处理玩家肩膀上的实体。
      • extractParrotVariantconvertParrotVariant*ShoulderParrot* - 处理玩家肩膀上的鹦鹉。
    • PlayerModelPart#CODEC - 模型部件的编解码器。
  • net.minecraft.world.entity.raid.Raids#getRaidCentersInChunk - 返回给定区块中的袭击中心数量。
  • net.minecraft.world.entity.vehicle.MinecartFurnace#addFuel - 向熔炉添加燃料以推动实体。
  • net.minecraft.world.item
    • BucketItem#getContent - 返回桶中持有的流体。
    • Item$TooltipContext#isPeaceful - 如果难度设置为和平,则返回 true。
    • ToolMaterial#COPPER - 铜工具材料。
    • WeatheringCopperItems - 一个记录,表示每个风化铜状态的物品。
  • net.minecraft.world.item.equipment
    • ArmorMaterials#COPPER - 铜盔甲材料。
    • EquipmentAssets#COPPER - 铜装备资源的键引用。
    • ResolvableProfile
      • skinPatch - 返回玩家皮肤引用。
      • $Static - 使用已解析的游戏配置文件。
      • $Dynamic - 在使用时动态解析游戏配置文件。
      • $Partial - 根据提供给组件的任何信息表示游戏配置文件的一部分。
  • net.minecraft.world.level
    • BaseCommandBlock$CloseableCommandBlockSource - 通常用于命令方块的命令源。
    • ChunkPos#contains - 给定的方块位置是否在区块中。
    • GameRules#RULE_SPAWNER_BLOCKS_ENABLED - 刷怪笼方块是否应生成实体。
    • Level
      • getEntityInAnyDimension - 通过 UUID 获取实体。
      • getPlayerInAnyDimension - 通过 UUID 获取玩家。
      • hasEntities - 返回提供的边界是否具有匹配类型和谓词的实体。
      • palettedContainerFactory - 返回用于创建调色板容器的工厂。
  • net.minecraft.world.level.border.WorldBorder$Settings#toWorldBorder - 从设置构造世界边界。
  • net.minecraft.world.level.block
    • Block#dropFromBlockInteractLootTable - 与方块交互时掉落战利品。
    • ChestBlock
      • chestCanConnectTo - 返回箱子是否可以与另一个方块合并。
      • getConnectedBlockPos - 获取箱子的连接方块位置。
      • getOpenChestSoundgetCloseChestSound - 返回箱子打开/关闭时播放的声音。
      • getChestType - 根据周围的箱子返回箱子的类型。
    • ChiseledBookShelfBlock#FACINGSLOT_*_OCCUPIED - 雕纹书架

Minecraft 1.21.9 -> 1.21.10 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

感谢:

  • @melanx 指出了一个拼写错误

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

小幅迁移

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

新增列表

  • net.minecraft.world.entity.decoration.HangingEntity#getPopBox - 返回一个边界框,指示如果发生碰撞,实体将从何处弹出。

变更列表

  • net.minecraft.world.level.block.state.BlockBehaviour#entityInside 现在接受一个 boolean 参数,指示实体是与方块相交还是在方块内部。

Minecraft 1.21.10 -> 1.21.11 模组迁移入门文档

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

本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。

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

感谢:

  • @xfacthd 对使用注解的一些合理推测
  • @dinnerbone 指出在单机世界中,gizmo 也可以在服务器上提交
  • @thatgravyboat 指出 Mth#clampedLerp 参数顺序的变化

资源包变更

原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。

重命名混乱

许多核心类、方法和参数被重新组织和重命名,同时保留了它们各自的功能。以下是最重要变更的列表。

ResourceLocationIdentifier

所有对 ResourceLocation 的引用,无论是在方法名称、参数还是其他类中,都已替换为 Identifier

util

大多数工具类已移至 net.minecraft.util。这些需要重新导入。

critereoncriterion

net.minecraft.advancements.critereon 已重命名为 net.minecraft.advancements.criterion。这些需要重新导入。

实体和对象子包

net.minecraft.client.modelnet.minecraft.world.entity 都已根据支持对象的类型重新组织为额外的子包。这些需要重新导入。

  • net.minecraft
    • BlockUtil -> .util.BlockUtil
    • FileUtil -> .util.FileUtil
    • ResourceLocationException -> IdentifierException
    • Util -> .util.Util
  • net.minecraft.advancements.critereon -> .advancements.criterion
  • net.minecraft.client.gui.screens.inventory.JigsawBlockEditScreen#isValidResourceLocation -> isValidIdentifier
  • net.minecraft.client.model
    • AbstractBoatModel -> .object.boat.AbstractBoatModel
    • AbstractEquineModel -> .animal.equine.AbstractEquineModel
    • AbstractPiglinModel -> .monster.piglin.AbstractPiglinModel
    • AbstractZombieModel -> .monster.zombie.AbstractZombieModel
    • AllayModel -> .animal.allay.AllayModel
    • ArmadilloModel -> .animal.armadillo.ArmadilloModel
    • ArmorStandArmorModel -> .object.armorstand.ArmorStandArmorModel
    • ArmorStandModel -> .object.armorstand.ArmorStandModel
    • ArrowModel -> .object.projectile.ArrowModel
    • AxolotlModel -> .animal.axolotl.AxolotlModel
    • BannerFlagModel -> .object.banner.BannerFlagModel
    • BannerModel -> .object.banner.BannerModel
    • BatModel -> .ambient.BatModel
    • BeeModel -> .animal.bee.BeeModel
    • BeeStingerModel -> .animal.bee.BeeStingerModel
    • BellModel -> .object.bell.BellModel
    • BlazeModel -> .monster.blaze.BlazeModel
    • BoatModel -> .object.boat.BoatModel
    • BoggedModel -> .monster.skeleton.BoggedModel
    • BookModel -> .object.book.BookModel
    • BreezeModel -> .monster.breeze.BreezeModel
    • CamelModel -> .animal.camel.CamelModel
    • CamelSaddleModel -> .animal.camel.CamelSaddleModel
    • CatModel -> .animal.feline.CatModel
    • ChestModel -> .object.chest.ChestModel
    • ChickenModel -> .animal.chicken.ChickenModel
    • CodModel -> .animal.fish.CodModel
    • ColdChickenModel -> .animal.chicken.ColdChickenModel
    • ColdCowModel -> .animal.cow.ColdCowModel
    • ColdPigModel -> .animal.pig.ColdPigModel
    • CopperGolemModel -> .animal.golem.CopperGolemModel
    • CopperGolemStatueModel -> .object.statue.CopperGolemStatueModel
    • CowModel -> .animal.cow.CowModel
    • CreakingModel -> .monster.creaking.CreakingModel
    • CreeperModel -> .monster.creeper.CreeperModel
    • DolphinModel -> .animal.dolphin.DolphinModel
    • DonkeyModel -> .animal.equine.DonkeyModel
    • DrownedModel -> .monster.zombie.DrownedModel
    • ElytraModel -> .object.equipment.ElytraModel
    • EndCrystalModel -> .object.crystal.EndCrystalModel
    • EndermanModel -> .monster.enderman.EndermanModel
    • EndermiteModel -> .monster.endermite.EndermiteModel
    • EquineSaddleModel -> .animal.equine.EquineSaddleModel
    • EvokerFangsModel -> .effects.EvokerFangsModel
    • FelineModel -> .animal.feline.FelineModel
    • FoxModel -> .animal.fox.FoxModel
    • FrogModel -> .animal.frog.FrogModel
    • GhastModel -> .monster.ghast.GhastModel
    • GiantZombieModel -> .monster.zombie.GiantZombieModel
    • GoatModel -> .animal.goat.GoatModel
    • GuardianModel -> .monster.guardian.GuardianModel
    • GuardianParticleModel -> .monster.guardian.GuardianParticleModel
    • HappyGhastHarnessModel -> .animal.ghast.HappyGhastHarnessModel
    • HappyGhastModel -> .animal.ghast.HappyGhastModel
    • HoglinModel -> .monster.hoglin.HoglinModel
    • HorseModel -> .animal.equine.HorseModel
    • IllagerModel -> .monster.illager.IllagerModel
    • IronGolemModel -> .animal.golem.IronGolemModel
    • LavaSlimeModel -> .monster.slime.MagmaCubeModel
    • LeashKnotModel -> .object.leash.LeashKnotModel
    • LlamaModel -> .animal.llama.LlamaModel
    • LlamaSpitModel -> .animal.llama.LlamaSpitModel
    • MinecartModel -> .object.cart.MinecartModel
    • OcelotModel -> .animal.feline.OcelotModel
    • PandaModel -> .animal.panda.PandaModel
    • ParrotModel -> .animal.parrot.ParrotModel
    • PhantomModel -> .monster.phantom.PhantomModel
    • PiglinHeadModel -> .object.skull.PiglinHeadModel
    • PiglinModel -> .monster.piglin.PiglinModel
    • PigModel -> .animal.pig.PigModel
    • PlayerCapeModel -> .player.PlayerCapeModel
    • PlayerEarsModel -> .player.PlayerEarsModel
    • PlayerModel -> .player.PlayerModel
    • PolarBearModel -> .animal.polarbear.PolarBearModel
    • PufferfishBigModel -> .animal.fish.PufferfishBigModel
    • PufferfishMidModel -> .animal.fish.PufferfishMidModel
    • PufferfishSmallModel -> .animal.fish.PufferfishSmallModel
    • RabbitModel -> .animal.rabbit.RabbitModel
    • RaftModel -> .object.boat.RaftModel
    • RavagerModel -> .monster.ravager.RavagerModel
    • SalmonModel -> .animal.fish.SalmonModel
    • SheepFurModel -> .animal.sheep.SheepFurModel
    • SheepModel -> .animal.sheep.SheepModel
    • ShieldModel -> .object.equipment.ShieldModel
    • ShulkerBulletModel -> .object.projectile.ShulkerBulletModel
    • ShulkerModel -> .monster.shulker.ShulkerModel
    • SilverfishModel -> .monster.silverfish.SilverfishModel
    • SkeletonModel -> .monster.skeleton.SkeletonModel
    • SkullModel -> .object.skull.SkullModel
    • SkullModelBase -> .object.skull.SkullModelBase
    • SlimeModel -> .monster.slime.SlimeModel
    • SnifferModel -> .animal.sniffer.SnifferModel
    • SnowGolemModel -> .animal.golem.SnowGolemModel
    • SpiderModel -> .monster.spider.SpiderModel
    • SpinAttackEffectModel -> .effects.SpinAttackEffectModel
    • SquidModel -> .animal.squid.SquidModel
    • StriderModel -> .monster.strider.StriderModel
    • TadpoleModel -> .animal.frog.TadpoleModel
    • TridentModel -> .object.projectile.TridentModel
    • TropicalFishModelA -> .animal.fish.TropicalFishSmallModel
    • TropicalFishModelB -> .animal.fish.TropicalFishLargeModel
    • TurtleModel -> .animal.turtle.TurtleModel
    • VexModel -> .monster.vex.VexModel
    • VillagerModel -> .npc.VillagerModel
    • WardenModel -> .monster.warden.WardenModel
    • WarmCowModel -> .animal.cow.WarmCowModel
    • WindChargeModel -> .object.projectile.WindChargeModel
    • WitchModel -> .monster.witch.WitchModel
    • WitherBossModel -> .monster.wither.WitherBossModel
    • WolfModel -> .animal.wolf.WolfModel
    • ZombieModel -> .monster.zombie.ZombieModel
    • ZombieVillagerModel -> .monster.zombie.ZombieVillagerModel
    • ZombifiedPiglinModel -> .monster.piglin.ZombifiedPiglinModel
  • net.minecraft.client.model.dragon
    • DragonHeadModel -> .model.object.skull.DragonHeadModel
    • EnderDragonModel -> .model.monster.dragon.EnderDragonModel
  • net.minecraft.client.resources.sounds
    • AbstractSoundInstance#location -> identifier
    • SoundInstance#getLocation -> getIdentifier
  • net.minecraft.client.searchtree
    • IdSearchTree
      • resourceLocationSearchTree -> identifierSearchTree
      • searchResourceLocation -> searchIdentifier
    • ResourceLocationSearchTree -> IdentifierSearchTree
  • net.minecraft.commands.arguments.ResourceLocationArgument -> IdentifierArgument
  • net.minecraft.network.FriendlyByteBuf#readResourceLocation, writeResourceLocation -> readIdentifier, writeIdentifier
  • net.minecraft.resources
    • ResourceKey#location -> identifier
    • ResourceLocation -> Identifier
  • net.minecraft.util.ResourceLocationPattern -> IdentifierPattern
  • net.minecraft.util.parsing.packrat.commands.ResourceLocationParseRule -> IdentifierParseRule
  • net.minecraft.world.entity.GlowSquid -> .animal.squid.GlowSquid
  • net.minecraft.world.entity.animal
    • AbstractCow -> .cow.AbstractCow
    • AbstractFish -> .fish.AbstractFish
    • AbstractGolem -> .golem.AbstractGolem
    • AbstractSchoolingFish -> .fish.AbstractSchoolingFish
    • Bee -> .bee.Bee
    • Cat -> .feline.Cat
    • CatVariant -> .feline.CatVariant
    • CatVariants -> .feline.CatVariants
    • Chicken -> .chicken.Chicken
    • ChickenVariant -> .chicken.ChickenVariant
    • ChickenVariants -> .chicken.ChickenVariants
    • Cod -> .fish.Cod
    • Cow -> .cow.Cow
    • CowVariant -> .cow.CowVariant
    • CowVariants -> .cow.CowVariants
    • Dolphin -> .dolphin.Dolphin
    • Fox -> .fox.Fox
    • HappyGhast -> .happyghast.HappyGhast
    • HappyGhastAi -> .happyghast.HappyGhastAi
    • IronGolem -> .golem.IronGolem
    • MushroomCow -> .cow.MushroomCow
    • Ocelot -> .feline.Ocelot
    • Panda -> .panda.Panda
    • Parrot -> .parrot.Parrot
    • Pig -> .pig.Pig
    • PigVariant -> .pig.PigVariant
    • PigVariants -> .pig.PigVariants
    • PolarBear -> .polarbear.PolarBear
    • Pufferfish -> .fish.Pufferfish
    • Rabbit -> .rabbit.Rabbit
    • Salmon -> .fish.Salmon
    • ShoulderRidingEntity -> .parrot.ShoulderRidingEntity
    • SnowGolem -> .golem.SnowGolem
    • Squid -> .squid.Squid
    • TropicalFish -> .fish.TropicalFish
    • Turtle -> .turtle.Turtle
    • WaterAnimal -> .fish.WaterAnimal
  • net.minecraft.world.entity.animal.coppergolem.* -> .animal.golem.*
  • net.minecraft.world.entity.animal.horse.* -> .animal.equine.*
  • net.minecraft.world.entity.boss.EnderDragonPart -> .enderdragon.EnderDragonPart
  • net.minecraft.world.entity.decoration
    • Painting -> .painting.Painting
    • PaintingVariant -> .painting.PaintingVariant
    • PaintingVariants -> .painting.PaintingVariants
  • net.minecraft.world.entity.monster
    • AbstractIllager -> .illager.AbstractIllager
    • AbstractSkeleton -> .skeleton.AbstractSkeleton
    • Bogged -> .skeleton.Bogged
    • CaveSpider -> .spider.CaveSpider
    • Drowned -> .zombie.Drowned
    • Evoker -> .illager.Evoker
    • Husk -> .zombie.Husk
    • Illusioner -> .illager.Illusioner
    • Parched -> .skeleton.Parached
    • Pillager -> .illager.Pillager
    • Skeleton -> .skeleton.Skeleton
    • SpellcasterIllager -> .illager.SpellcasterIllager
    • Spider -> .spider.Spider
    • Stray -> .skeleton.Stray
    • Vindicator -> .illager.Vindicator
    • WitherSkeleton -> .skeleton.WitherSkeleton
    • Zombie -> .zombie.Zombie
    • ZombieVillager -> .zombie.ZombieVillager
    • ZombifiedPiglin -> .zombie.ZombifiedPiglin
  • net.minecraft.world.entity.npc
    • AbstractVillager -> .villager.AbstractVillager
    • Villager -> .villager.Villager
    • VillagerData -> .villager.VillagerData
    • VillagerDataHolder -> .villager.VillagerDataHolder
    • VillagerProfession -> .villager.VillagerProfession
    • VillagerTrades -> .villager.VillagerTrades
    • VillagerType -> .villager.VillagerType
    • WanderingTrader -> .wanderingtrader.WanderingTrader
    • WanderingTraderSpawner -> .wanderingtrader.WanderingTraderSpawner
  • net.minecraft.world.entity.projectile
    • AbstractArrow -> .arrow.AbstractArrow
    • AbstractHurtingProjectile -> .hurtingprojectile.AbstractHurtingProjectile
    • AbstractThrownPotion -> .throwableitemprojectile.AbstractThrownPotion
    • Arrow -> .arrow.Arrow
    • DragonFireball -> .hurtingprojectile.DragonFireball
    • Fireball -> .hurtingprojectile.Fireball
    • LargeFireball -> .hurtingprojectile.LargeFireball
    • SmallFireball -> .hurtingprojectile.SmallFireball
    • Snowball -> .throwableitemprojectile.Snowball
    • SpectralArrow -> .arrow.SpectralArrow
    • ThrowableItemProjectile -> .throwableitemprojectile.ThrowableItemProjectile
    • ThrownEgg -> .throwableitemprojectile.ThrownEgg
    • ThrownEnderpearl -> .throwableitemprojectile.ThrownEnderpearl
    • ThrownExperienceBottle -> .throwableitemprojectile.ThrownExperienceBottle
    • ThrownLingeringPotion -> .throwableitemprojectile.ThrownLingeringPotion
    • ThrownSplashPotion -> .throwableitemprojectile.ThrownSplashPotion
    • ThrownTrident -> .arrow.ThrownTrident
    • WitherSkull -> .hurtingprojectile.WitherSkull
  • net.minecraft.world.entity.projectile.windcharge.* -> .projectile.hurtingprojectile.windcharge.*
  • net.minecraft.world.entity.vehicle
    • AbstractBoat -> .boat.AbstractBoat
    • AbstractChestBoat -> .boat.AbstractChestBoat
    • AbstractMinecart -> .minecart.AbstractMinecart
    • AbstractMinecartContainer -> .minecart.AbstractMinecartContainer
    • Boat -> .boat.Boat
    • ChestBoat -> .boat.ChestBoat
    • ChestRaft -> .boat.ChestRaft
    • Minecart -> .minecart.Minecart
    • MinecartBehavior -> .minecart.MinecartBehavior
    • MinecartChest -> .minecart.MinecartChest
    • MinecartCommandBlock -> .minecart.MinecartCommandBlock
    • MinecartFurnace -> .minecart.MinecartFurnace
    • MinecartHopper -> .minecart.MinecartHopper
    • MinecartSpawner -> .minecart.MinecartSpawner
    • MinecartTNT -> .minecart.MinecartTNT
    • NewMinecartBehavior -> .minecart.NewMinecartBehavior
    • OldMinecartBehavior -> .minecart.OldMinecartBehavior
    • Raft -> .boat.Raft
  • net.minecraft.world.level.gamerules.GameRule#getResourceLocation -> getIdentifier

哦,又来了,一次渲染重写

渲染管线的更多部分已被重写,主要集中在采样器、RenderType 的创建和 mipmap 上。

采样器的分离

Blaze3d 已将读取纹理数据时的 AddressModeFilterMode 设置分离到 GpuSampler 中。顾名思义,GpuSampler 定义了如何从缓冲区(如纹理)采样数据。GpuSampler 包含四个方法:getAddressModeU / getAddressModeV 用于确定采样器在读取 UV 位置时的行为(重复或钳位),getMinFilter / getMagFilter 用于分别确定如何缩小或放大纹理(最近邻或线性),getMaxAnisotropy 用于可用的最大各向异性过滤级别,以及 getMaxLod 用于纹理的最大细节级别。

采样器可以通过 GpuDevice#createSampler 创建,但除非您想指定大于 1 的不同各向异性过滤级别,或者最大细节级别不是 01000,否则没有必要。由于只有 32 种可能的组合,原版创建了所有 GpuSampler 并将它们存储在一个缓存中,可通过 RenderSystem#getSamplerCache 然后 SamplerCache#getSampler 访问:

// 直接调用
GpuSampler sampler = RenderSystem.getDevice().createSampler(
    // U 地址模式
    AddressMode.CLAMP_TO_EDGE,
    // V 地址模式
    AddressMode.CLAMP_TO_EDGE,
    // 缩小过滤器
    FilterMode.LINEAR,
    // 放大过滤器
    FilterMode.NEAREST,
    // 最大各向异性过滤级别
    // 原版对于等级渲染使用 1、2、4 或 8
    4f,
    // 纹理的最大细节级别
    // 原版对于默认使用 0,
    // 或对于移动对象和上传到图集使用空 optional。
    OptionalDouble.of(0.0)
);

// 采样器缓存方法
GpuSampler sampler = RenderSystem.getSamplerCache().getSampler(
    // U 地址模式
    AddressMode.CLAMP_TO_EDGE,
    // V 地址模式
    AddressMode.CLAMP_TO_EDGE,
    // 缩小过滤器
    FilterMode.LINEAR,
    // 放大过滤器
    FilterMode.NEAREST,
    // 是否为最大细节级别使用 1000 或 0
    true
);

要使采样器用于纹理,当在渲染通道中绑定纹理时(通过 RenderPass#bindTexture),您现在必须指定要使用的采样器以及纹理视图:

try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(...)) {
    // 设置其他参数
    pass.bindTexture(
        // sampler2D 统一变量的名称,通常在片段着色器中
        "Sampler0",
        // 要采样的纹理
        ...,
        // 要使用的采样器
        sampler
    );

    // 绘制缓冲区
}

从用户角度来看,设置后处理器没有变化,因为只能选择钳位到边缘的地址模式。

RenderType 洗牌

创建 RenderType 已在一定程度上被重做。虽然先前实现中的大多数功能仍然存在,但它们已更改以匹配新的渲染系统,其中直接 OpenGL 被抽象化,仅通过其定义的管道和 RenderSystem 访问。

现有类型

现有类型已从 RenderType 移至 RenderTypes(例如,RenderType#solid -> RenderTypes#solid)。

自定义类型

最初,要创建 RenderType,您会使用 RenderStateShard 构造一个 $CompositeState。每个 RenderStateShard 将定义在构建某些网格时如何设置和拆除通道,无论是设置纹理、渲染目标、模型变换等。然后,$CompositeState 将被构建以供任何需要的渲染应用使用。

新系统将渲染定义拆分为两部分:RenderSetup 和我们的 RenderType。顾名思义,RenderSetup 设置渲染器,以便在绘制到纹理时使用。拆除被完全移除,因为它要么在绘制 RenderType 时直接处理,要么使用可以丢弃的新构造的状态。另一方面,RenderType 只是一个命名的 RenderSetup。它只处理绘制网格数据,并使设置的某些字段公开以供在其他缓冲区实现中使用。多个类型可以具有相同的 RenderSetup,因为许多现有类型动态填充采样器使用的纹理和/或对象的轮廓。

可以通过其构建器 RenderSetup#Builder 创建 RenderSetup,提供要使用的 RenderPipeline。一旦设置了构建器属性,就可以通过 RenderSetup$RenderSetupBuilder#createRenderSetup 创建实际的设置:

public static final RenderSetup EXAMPLE_SETUP = RenderSetup.builder(
    // 要使用的管线。
    // 这可能会影响设置允许哪些设置。
    RenderPipelines.ITEM_ENTITY_TRANSLUCENT_CULL
)
    // 指定要绑定到提供的采样器的纹理。
    // 采样器必须由管线通过 `RenderPipeline$Builder#withSampler` 定义。
    // 纹理表示为绝对位置。
    .withTexture(
        // 'Sampler0' 由管线定义。
        "Sampler0",
        // 指向 'assets/minecraft/entity/wolf/wolf_armor_crackiness_low.png'。
        Identifier.withDefaultNamespace("textures/entity/wolf/wolf_armor_crackiness_low.png"),
        // 一个可选的提供的 `GpuSampler`,用于对纹理进行采样。
        // 返回的值将在第一次解析后被缓存。
        () -> RenderSystem.getSamplerCache().getClampToEdge(FilterMode.NEAREST)
    )
    // 设置后,允许管线使用光照纹理。
    // 'Sampler2' 必须由管线通过 `RenderPipeline$Builder#withSampler` 定义。
    .useLightmap()
    // 设置后,允许管线使用覆盖纹理。
    // 'Sampler1' 必须由管线通过 `RenderPipeline$Builder#withSampler` 定义。
    .useOverlay()
    // 设置后,使用 `RenderTypes#crumbling` 根据实体模型的破坏进度叠加方块破坏阶段。
    // 这仅在 `ModelFeatureRenderer` 中实现。
    .affectsCrumbling()
    // 设置后,根据 `RenderSystem#getProjectionType` 中设置的 `ProjectionType` 对四边形进行排序。
    // 这仅在从 `MultiBufferSource$BufferSource` 获取缓冲区时实现。
    .sortOnUpload()
    // 设置使用的缓冲区的初始容量。
    // 这仅在 `RenderBuffers` 中构造初始缓冲区时使用。
    // 所有自定义的源应用都已经有一些具有确定大小的缓冲区。
    .bufferSize(786432)
    // 一个对象包装的消费者,用于变换模型视图矩阵。
    // 原版实现在 `LayeringTransform` 中,通过投影类型应用变换:
    // - `NO_LAYERING`: 不执行任何操作。
    // - `VIEW_OFFSET_Z_LAYERING`: 根据其 `ProjectionType` 将 Z 偏移 1
    // - `VIEW_OFFSET_Z_LAYERING_FORWARD`: 根据其 `ProjectionType` 将 Z 偏移 -11
    .setLayeringTransform(
        // 我们也可以构造一个新的变换
        new LayeringTransform(
            // 变换的名称
            "examplemod:example_layer",
            // 变换不应推入或弹出堆栈
            // 仅平移、缩放或旋转
            stack -> stack.translate(0f, 0.1f, 0f)
        )
    )
    // 设置此设置应写入的输出目标,
    // 除非被 `RenderSystem#output*Override` 纹理覆盖。
    // 这通常是主目标,尽管它可以是其他原版目标,
    // 或者如果您计划处理它,也可以是自定义目标。
    .setOutputTarget(OutputTarget.MAIN_TARGET)
    // 一个对象包装的供应商,提供纹理矩阵。
    // 这通常用于在片段着色器中采样之前修改顶点着色器中的纹理 UV 坐标。
    // 原版仅将此用于闪光效果和旋风人/能量效果:
    // - `DEFAULT_TEXTURING`: 不执行任何操作。
    // - `GLINT_TEXTURING`: 根据闪光速度平移,旋转 pi/18,并按 8 缩放。
    // - `ENTITY_GLINT_TEXTURING`: 根据闪光速度平移,旋转 pi/18,并按 0.5 缩放。
    // - `ARMOR_ENTITY_GLINT_TEXTURING`: 根据闪光速度平移,旋转 pi/18,并按 0.16 缩放。
    // - `$OffsetTextureTransform`: 按提供的 XY 坐标平移纹理。
    .setTextureTransform(
        // 我们也可以构造一个新的变换
        new TextureTransform(
            // 变换的名称
            "examplemod:example_texture",
            // 要应用于纹理的变换
            () -> new Matrix4f().translation(0f, 1f, 0f).scale(1.5f)
        )
    )
    // 设置应如何处理网格的轮廓:
    // - `NONE`: 不执行任何操作。
    // - `IS_OUTLINE`: 这是一个轮廓,应写入轮廓缓冲区源。
    // - `AFFECTS_OUTLINE`: 这定义了轮廓的形状,应使用 `RenderTypes#OUTLINE` 绘制它。
    // 在写入轮廓缓冲区源时检查,
    // 或者如果功能的轮廓颜色不为 0
    .setOutline(RenderSetup.OutlineProperty.AFFECTS_OUTLINE)
    // 构建用于渲染类型的设置。
    .createRenderSetup();

然后,可以通过 create 创建 RenderType

public static final RenderType EXAMPLE_TYPE = RenderType.create(
    // 用于调试的类型名称
    "examplemod:example_type",
    // 要使用的渲染设置
    EXAMPLE_SETUP
);

可以使用 RenderType#drawMeshData 写入输出目标。

Mipmap 策略元数据

纹理的 mcmeta 现在可以在 textures 部分中指定要使用的 mipmap_strategy。有四种可用的策略,auto 在没有透明度时默认为 mean,在有透明度时默认为 cutout

策略描述
mean默认策略,对当前 mipmap 级别的四个像素之间的颜色进行平均。
cutoutmean 相同,但所有级别都是从原始纹理生成的,使用 0.2 的阈值将 alpha 捕捉到 0 或 1。
strict_cutoutcutout 相同,但使用 0.6 的阈值设置 alpha 捕捉。
dark_cutoutmean 相同,但仅当周围像素的 alpha 不为 0 时才将其包含在平均值中。
// 在 `assets/examplemod/textures/block/example/example_block.png.mcmeta
{
    "texture": {
        // 使用选定的策略
        "mipmap_strategy": "cutout",
        // 确定在判断像素是完全不透明还是完全透明时,
        // 截止值应偏置多少。
        // 较大的数字意味着更高的 alpha 截止值,
        // 而较低的值使用较低的 alpha 截止值。
        "alpha_cutoff_bias": 0.2
    }
}

方块和地形拆分

由独立方块和地形使用的 RenderPipeline 已被拆分为单独的管线:分别带有前缀 _BLOCK_TERRAIN。这包括实体、切割、半透明和绊线管线。半透明管线没有方块变体。

物品图集

方块图集不再包含专门用于物品的纹理。这些已移至它们自己的图集,名为 minecraft:items,其 id 存储在 AtlasIds#ITEMS

如果给定的 Material 可以同时使用方块和物品纹理,则应使用 ModelManager#BLOCK_OR_ITEM 特殊情况提供。

  • com.mojang.blaze3d.buffers
    • GpuBuffersize 现在使用 long 作为大小
      • slice 现在使用 long 作为长度和偏移
    • GpuBufferSlice 现在使用 long 作为长度和偏移
  • com.mojang.blaze3d.opengl
    • BufferStorage
      • createBuffer 现在使用 long 作为大小
      • mapBuffer 现在使用 long 作为长度和偏移
    • DirectStateAccess
      • bufferSubData 现在使用 long 作为偏移
      • mapBufferRangeflushMappedBufferRangecopyBufferSubData 现在使用 long 作为长度和偏移
    • GlBuffer 现在使用 long 作为大小
    • GlDevice 现在接受 ShaderSource 而不是 BiFunction
      • getOrCompileShader 现在接受 ShaderSource 而不是 BiFunction
    • GlRenderPass
      • samplers 现在是一个字符串到 GlRenderPass$TextureViewAndSampler 的哈希映射
      • $TextureViewAndSampler - 一个记录,定义了一个采样器及其采样的纹理。
    • GlSampler - GPU 采样器的 OpenGL 实现。
    • GlStateManager
      • _glBufferSubData 现在使用 long 作为偏移
      • _glMapBufferRange 现在使用 long 作为长度和偏移
    • GlTexture#modesDirtyflushModeChanges 已移除
    • GlTextureView#getFbo - 获取纹理的帧缓冲区对象,如果存在则使用缓存。
  • com.mojang.blaze3d.pipeline.RenderTarget#filterModesetFilterMode 已移除
  • com.mojang.blaze3d.platform.TextureUtil
    • solidify - 通过打包和解包像素来修改纹理,以更好地帮助 mipmap 内的非暗化内部。
    • fillEmptyAreasWithDarkColor - 将空像素设置为一个 RGB 值为图像中最暗颜色的空像素。
  • com.mojang.blaze3d.shaders.ShaderSource - 一个函数式接口,从其 id 和类型以字符串形式获取着色器源。
  • com.mojang.blaze3d.systems
    • CommandEncoder#copyTextureToBuffer 现在使用 long 作为偏移
    • GpuDevice
      • createSampler - 为某个源到目标创建一个采样器,具有所需的地址和过滤模式。
      • precompilePipeline 现在接受 ShaderSource 而不是 BiFunction
      • getMaxSupportedAnisotropy - 硬件支持的最大各向异性过滤级别。
      • createBuffer 现在使用 long 作为大小
    • RenderPass#bindTexture 现在接受 GpuSampler
    • RenderSystem 现在使用 long 作为大小
      • samplerCache - 返回一个包含所有可能组合的采样器缓存。
      • TEXTURE_COUNT 已移除
      • setupOverlayColorteardownOverlayColor 已移除
      • setShaderTexturegetShaderTexture 已移除
      • setTextureMatrixresetTextureMatrixgetTextureMatrix 已移除
      • lineWidth -> VertexConsumer#setLineWidth
      • getShaderLineWidth -> Window#getAppropriateLineWidth
      • initRenderer 现在接受 ShaderSource 而不是 BiFunction
    • SamplerCache - 一个缓存,包含渲染器可能使用的所有采样器。
  • com.mojang.blaze3d.textures
    • GpuSampler - 一个具有指定 UV 地址模式和缩小及放大过滤器的缓冲区采样器。
    • GpuTexture
      • addressModeU -> GpuSampler#getAddressModeU
      • addressModeV -> GpuSampler#getAddressModeV
      • minFilter -> GpuSampler#getMinFilter
      • magFilter -> GpuSampler#getMagFilter
      • setAddressModesetTextureFilter 已被 SamplerCache#getSampler 取代,不是一对一
      • useMipmapssetUseMipmaps 已移除
  • net.minecraft.client
    • Options#textureFiltering - 从一定角度或远处观看时选择的纹理采样方法。
    • TextureFilteringMethod - 从一定角度或远处观看纹理时的采样方法。
  • net.minecraft.client.gui.render.TextureSetup 现在接受每个纹理的 GpuSampler
    • 这也包括静态构造函数
  • net.minecraft.client.particle.SingleQuadParticle$Layer#ITEMS - 用于具有物品纹理的粒子的层。
  • net.minecraft.client.renderer
    • FaceInfo
      • $Constants -> $Extent
      • $VertexInfo 现在是一个记录
    • ItemBlockRenderTypes#getRenderType(ItemStack)
    • LightTexture#turnOffLightLayerturnOnLightLayer 已移除
    • LevelRenderer#resetSampler - 重置区块层采样器。
    • PostPass
      • $Input#bilinear - 是否使用双线性过滤器。
      • $TextureInput 现在接受一个 boolean,表示是否使用双线性过滤器
    • RenderPipelines
      • SOLID -> SOLID_BLOCKSOLID_TERRAIN
      • CUTOUT -> CUTOUT_BLOCKCUTOUT_TERRAIN
      • CUTOUT_MIPPED 已移除
      • TRANSLUCENT -> TRANSLUCENT_TERRAIN
      • TRIPWIRE -> TRIPWIRE_BLOCKTRIPWIRE_TERRAIN
      • ANIMATE_SPRITE_SNIPPETANIMATE_SPRITE_BLITANIMATE_SPRITE_INTERPOLATION - 用于动画精灵的管线。
    • RenderStateShard 已被 RenderSetup 取代,不是一对一
      • $LightmapStateShard -> RenderSetup#useLightmap
      • $OverlayStateShard -> RenderSetup#useOverlay
      • $MultiTextureStateShard$TextureStateShard -> RenderSetup#textures
      • $LayeringStateShard -> RenderSetup#layeringTransformLayeringTransform
      • $LineStateShard -> VertexConsumer#setLineWidth
      • $OutputStateShard -> RenderSetup#outputTargetOutputTarget
      • $TexturingStateShard$OffsetTexturingStateShard -> RenderSetup#textureTransformTextureTransform
    • RenderType 已被拆分为两个独立的概念,不是一对一
      • 所有存储的 RenderType 已移至 RenderTypes
      • 实际的类用法已移至 .rendertype.RenderType,在那里它执行 $CompositeRenderType 的工作
    • Sheets#translucentBlockItemSheet - 用于半透明方块物品的渲染类型。
  • net.minecraft.client.renderer.block
    • BlockRenderDispatcher 不再接受提供的 SpecialBlockModelRenderer
    • LiquidBlockRenderer 现在接受 MaterialSet
      • setupSprites 已移至 LiquidBlockRenderer 构造函数中
  • net.minecraft.client.renderer.block.model
    • BakedQuad
      • vertices -> position*packedUV*,不是一对一
      • position - 根据索引获取位置向量。
      • packedUV - 根据索引获取打包的 UV。
    • BlockElementRotation 现在接受 Vector3fc 作为原点,以及 Matrix4fc 变换
      • 构造函数也接受 $RotationValue 而不是 Direction$Axis 和角度 float
      • $EulerXYZRotation - 以度为单位的 XYZ 旋转。
      • $RotationValue - 一个定义旋转变换的接口。
      • $SingleAxisRotation - 围绕单个轴以度为单位的旋转。
    • FaceBakery
      • VERTEX_COUNT -> BakedQuad#VERTEX_COUNT
      • VERTEX_INT_SIZECOLOR_INDEXUV_INDEX 已移除
      • bakeQuad 现在接受 ModelBaker$PartCache
      • extractPositions 已移除
    • SimpleModelWrapper#bake 现在返回 BlockModelPart
    • SimpleUnbakedGeometry#bake 现在接受 ModelBaker 而不是 SpriteGetter
    • TextureSlots$parseTextureMap 不再接受 Identifier
    • Variant
      • withZRot - 围绕 Z 轴旋转模型状态。
      • $SimpleModelState 现在接受一个 Z Quadrant
        • withZ - 设置模型状态的 Z 象限。
    • VariantMutator#Z_ROT - 围绕 Z 轴旋转模型。
  • net.minecraft.client.renderer.chunk
    • ChunkSectionLayer 不再接受是否使用 mipmap
      • CUTOUT_MIPPED 已移除
      • texture 已移除
    • ChunkSectionsToRender 现在接受 GpuTextureView
      • dynamicTransforms -> chunkSectionInfos
      • renderGroup 现在接受 GpuSampler
  • net.minecraft.client.renderer.item
    • BlockModelWrapper 构造函数现在是包私有的
      • computeExtents 现在返回 Vector3fc 的数组
    • ItemStackRenderState$LayerRenderState
      • NO_EXTENTS_SUPPLIER 现在是一个提供的 Vector3fc 数组
      • setExtents 现在接受一个提供的 Vector3fc 数组
  • net.minecraft.client.renderer.rendertype.RenderTypes
    • MOVING_BLOCK_SAMPLER - 用于移动中方块的采样器。
    • solid -> solidMovingBlock
    • cutout -> cutoutMovingBlock
    • tripwire -> tripwireMovingBlock
  • net.minecraft.client.renderer.texture
    • AbstractTexture#setUseMipmaps 已移除
    • MipmapGenerator#generateMipLevels 现在接受纹理的名称、一个 MipmapStrategy 来确定特定纹理应如何进行 mipmap,以及一个用于 alpha 截止偏置的 float
    • MipmapStrategy - 一个枚举,定义了在为纹理构造 mipmap 时使用的策略。
    • OverlayTexture#setupOverlayColorteardownOverlayColorgetTextureView 取代,不是一对一
    • SpriteContents 现在接受一个可选的 TextureMetadataSection 来确定精灵的元数据
      • UBO_SIZE - 精灵内容的统一缓冲区对象大小。
      • createTicker -> createAnimationState,不是一对一
      • uploadFirstFrame 不再接受纹理 int,而是接受一个 mip 级别 int
      • $AnimatedTexture#createTickeruploadFirstFrame -> createAnimationState,不是一对一
      • $Ticker -> $AnimationState,不是一对一
        • tickAndUpload -> tickgetDrawUboneedsToDrawdrawToAtlas;不是一对一
    • SpriteTicker 接口已移除
    • Stitcher 现在接受各向异性过滤级别
      • $Holder(T, int) 已移除
      • $Region#walk 现在接受一个填充 int
      • $SpriteLoader 不再接受最小宽度/高度
        • load 现在接受一个填充 int
    • TextureAtlas 现在实现 TickableTexture 而不是 Tickable
    • TextureAtlasSprite 现在实现 AutoCloseable
      • 构造函数接受一个填充 int
      • createTicker -> createAnimationState,不是一对一
      • getUOffsetgetVOffsetuvShrinkRatio 已移除
      • uploadFirstFrame 现在接受 mip 级别 int
      • uploadSpriteUbo - 将图集精灵上传到缓冲区。
      • $Ticker 接口已移除
    • TextureManager 不再实现 Tickable
    • Tickable -> TickableTexture
  • net.minecraft.client.renderer.texture.atlas
    • SpriteSource$SpriteSupplier -> $DiscardableLoader
      • Function 超接口现在表示为 $Loader
        • apply -> get
    • SpriteSourceList#list 现在返回一个 SpriteSource$Loader 列表
  • net.minecraft.client.resources.metadata.texture.TextureMetadataSection 现在接受一个 MipmapStrategy 来确定特定纹理应如何进行 mipmap,以及一个用于 alpha 截止偏置的 float
  • net.minecraft.client.resources.model
    • ModelBaker
      • missingBlockModelPart - 缺失的方块模型。
      • parts - 先前构造的向量的缓存。
      • $PartCache - 一个缓存,用于内部存储四边形中先前构造的顶点。
    • ModelBakery
      • *_STILL - 流体的静态纹理位置。
      • $MissingModels 现在接受一个 BlockModelPart 缺失模型
    • ModelManager
      • BLOCK_OR_ITEM - 一个特殊情况,导致模型管理器同时检查物品和方块图集。
      • specialBlockModelRenderer 现在返回原始渲染器而不是提供的值。
  • net.minecraft.data.AtlasIds#ITEMS - 物品图集标识符。
  • net.minecraft.world.level.block.LeavesBlock#setCutoutLeaves - 设置树叶是否使用切割渲染。

Gizmo 控件

Gizmo 是提交和渲染解耦的最新迭代,这次用于调试渲染器。然而,提交 gizmo 进行渲染的底层结构要复杂得多,因为调试渲染器几乎可以在客户端进程的任何时刻提交对象。

什么是 Gizmo?

一个 Gizmo 基本上是一个对象,它提交一些对象图元——特别是点、线、三角形扇、四边形和文本——进行渲染。每个 gizmo 通过 emit 将这些图元串在一起形成所需的形状。在渲染过程中,它们使用 RenderPipelines#DEBUG_* 管线将其图元渲染到屏幕。创建一个新的 gizmo 就像扩展接口一样简单:

// 存储一些参数,如渲染状态,以提交元素图元
public record ExampleGizmo(Vec3 start, Vec3 end) implements Gizmo {

    @Override
    public void emit(GizmoPrimitives gizmos, float alphaMultiplier) {
        // 在此处提交任何元素
        gizmos.addLine(this.start, this.end, ARGB.multiplyAlpha(0, alphaMultiplier), 3f);
    }
}

实际提交元素通过 Gizmos#addGizmo 发生。这会将 gizmo 存储起来,以便在 Minecraft#tick 或客户端上的任何渲染期间发出并绘制到屏幕——这也是调试渲染器发出 gizmo 的方式,在单机世界中通过 IntegratedServer#tickServer,或通过任一侧的数据包处理。Gizmos 中的所有方法都在内部调用 addGizmo,这就是为什么该方法通常在其类之外不存在的原因:

// 在 GameRenderer#render 的某处

Gizmos.addGizmo(new ExampleGizmo(Vec3.ZERO, Vec3.X_AXIS));

// 内部调用 addGizmo
Gizmos.point(Vec3.ZERO, 0, 5f);

调用 addGizmo 返回一个 GizmoProperties,它在绘制元素时设置一些属性,假设 GizmoCollector 不是 NOOPGizmoProperties 提供了三个方法:

方法描述
setAlwaysOnTop在渲染前清除深度纹理。
persistForMillis在消失前将 gizmo 在屏幕上保持指定的时间。
fadeOut当持续一定时间后,使消失过程淡出。

组合在一起

那么,您如何几乎在客户端管道的任何地方提交 gizmo 进行渲染?这一切都从 Gizmos#withCollectorSimpleGizmoCollector 开始。

SimpleGizmoCollector 基本上只是一个保存收集到的要渲染的 gizmo 的列表。在渲染过程中,调用 SimpleGizmoCollector#drainGizmos,将 gizmo 复制到一个单独的列表中,供渲染器通过熟悉的帧通道和缓冲区源在 Gizmo#emit 之前使用。然后,drainGizmos 根据 GizmoProperties#persistForMillis 清除内部列表,如果未指定则立即清除,以供下一帧使用。

为了实际收集这些元素,有一个相当复杂的过程。MinecraftLevelRendererIntegratedServer 都有自己的 SimpleGizmoCollector。这是通过使用 Gizmo#withCollector 设置收集器来完成的,它返回一个 Gizmos$TemporaryCollection。该集合是 AutoCloseable 的,当关闭时,会释放本地线程上持有的收集器。因此,收集器被包装在 try-with-resources 中,以便在这些期间促进提交。然后,在调试通道期间,每Tick的 gizmo 与每帧的 gizmo 合并,并通过 addTemporaryGizmos 绘制到屏幕上,实际上是在 LevelRenderer#renderLevel 的最后一刻。在单机世界中,IntegratedServer 的 gizmo 存储在一个易失性字段中,允许从客户端线程访问它。

  • net.minecraft.client.Minecraft
    • collectPerTickGizmos - 返回所有要发出的 gizmo 的集合。
    • getPerTickGizmos - 获取要绘制到屏幕的 gizmo。
  • net.minecraft.client.renderer
    • LevelRenderer#collectPerFrameGizmos - 返回所有要发出的 gizmo 的集合。
    • OrderedSubmitNodeCollector#submitHitbox 已移除
    • ShapeRenderer
      • renderShape 现在接受一个线宽 float
      • renderLineBox -> Gizmos#cuboid,不是一对一
      • addChainedFilledBoxVertices -> Gizmos#cuboid,不是一对一
      • renderFace -> Gizmos#rect,不是一对一
      • renderVector -> Gizmos#line,不是一对一
    • SubmitNodeCollection#getHitboxSubmits 已移除
    • SubmitNodeStorage$HitboxSubmit 记录已移除
  • net.minecraft.client.renderer.debug
    • DebugRenderer
      • render -> emitGizmos,不再接受 PoseStackBufferSourceboolean,现在接受部分刻 float
      • renderFilledUnitCube -> Gizmos#cuboid,不是一对一
      • renderFilledBox -> Gizmos#cuboid,不是一对一
      • renderTextOverBlock -> Gizmos#billboardTextOverBlock,不是一对一
      • renderTextOverMob -> Gizmos#billboardTextOverMob,不是一对一
      • renderFloatingText -> Gizmos#billboardText,不是一对一
      • renderVoxelShape -> LevelRenderer#renderHitOutline,现在是私有的,不是一对一
      • SimpleDebugRenderer$render -> emitGizmos,不再接受 PoseStackBufferSourceboolean,现在接受部分刻 float
    • GameTestBlockHighlightRenderer
      • render -> emitGizmos,不接受参数
      • renderMarker 不再接受 PoseStack 或缓冲区源
      • $Marker#get* 已移除
    • LightDebugRenderer 现在接受两个标志,决定是否显示块光或天空光
    • PathfindingRenderer#renderPathrenderPathLine 不再接受 PoseStack 或缓冲区源
  • net.minecraft.client.renderer.entity.EntityRenderer#extractAdditionalHitboxes 已移除
  • net.minecraft.client.renderer.entity.state
    • EntityRenderState#hitboxesRenderStateserverHitboxesRenderState 已移除
    • HitboxesRenderState 类已移除
    • ServerHitboxesRenderState 类已移除
  • net.minecraft.client.renderer.feature.HitboxFeatureRenderer -> EntityHitboxDebugRenderer,不是一对一
  • net.minecraft.client.renderer.gizmos.DrawableGizmoPrimitives - 用于图元形状或 gizmo 的存储和渲染器。
  • net.minecraft.client.renderer.texture
    • AbstractTexture
      • samplergetSampler - 返回纹理使用的 GpuSampler
      • setClamp -> GpuSampler#getAddressMode*,不是一对一
      • setFilter -> GpuSampler#get*Filter,不是一对一
    • ReloadableTexture 不再接受地址模式和过滤 boolean
  • net.minecraft.client.server.IntegratedServer#getPerTickGizmos - 获取当前Tick要绘制到屏幕的 gizmo。
  • net.minecraft.gizmos
    • ArrowGizmo - 一个绘制箭头的 gizmo。
    • CircleGizmo - 一个绘制近似圆形(使用二十个顶点)的 gizmo。
    • CuboidGizmo - 一个绘制矩形棱柱的 gizmo。
    • Gizmo - 一个可以发出简单形状图元进行绘制的对象。
    • GizmoCollector - 一个只添加的收集器。
    • GizmoPrimitives - 可以绘制的形状图元。
    • GizmoProperties - 应用于 gizmo 应如何绘制的属性。
    • Gizmos - 一个用于创建 gizmo 和收集它们的静态方法集合。
    • GizmoStyle - 一个属性持有者,用于定义 gizmo 应如何绘制。这些由 gizmo 本身使用,而不是实际图元。
    • LineGizmo - 一个绘制线的 gizmo。
    • PointGizmo - 一个绘制点的 gizmo。
    • RectGizmo - 一个绘制矩形的 gizmo。
    • SimpleGizmoCollector - 一个收集器实现,用于在将 gizmo 发送到渲染之前添加它们。
    • TextGizmo - 一个绘制文本的 gizmo。
  • net.minecraft.server.MinecraftServer#processPacketsAndTick - 处理服务器Tick和数据包处理。

权限大修

权限级别整数已被扩展为一个既简单又复杂的新系统。有三个主要部分:PermissionPermissionSetPermissionCheck

权限

Permission 在功能上是定义某种状态的数据对象。原版提供了两种类型的权限:Permission$Atom,它只是一个唯一的单元对象;以及 Permission$HasCommandLevel,它持有命令所需的 PermissionLevel。这两个数据对象都注册为映射编解码器,用于转储命令报告。

// 尝试查询管理员级别权限。
public static final Permission COMMANDS_MODERATOR = new Permission.HasCommandLevel(PermissionLevel.MODERATORS);

可以通过某个扩展 Permission 的类或记录来创建自定义权限,并将关联的 MapCodec 注册到其静态注册表:

// 这不检查用户是否具有给定的权限
// 它仅仅只是持有表示权限状态的数据
public record HasExamplePermission(int state) implements Permission {
    public static final MapCodec<HasExamplePermission> MAP_CODEC = Codec.INT.fieldOf("state")
        .xmap(HasExamplePermission::new, HasExamplePermission::state);
    
    @Override
    public MapCodec<HasExamplePermission> codec() {
        return HasExamplePermission.MAP_CODEC;
    }
}

// 在某个注册处理程序中
Registry.register(
    BuiltInRegistries.PERMISSION_TYPE
    Identifier.withNamespaceAndPath("examplemod", "has_example_permission"),
    HasExamplePermission.MAP_CODEC
);

// 存储权限以供使用
public static final Permission HAS_STATE_ONE = new HasExamplePermission(1);

权限集

如果 Permission 定义了可查询的状态,那么 PermissionSet 就是用户实际拥有的权限。PermissionSet 是一个函数式接口,用于检查用户是否具有所需的状态(通过 hasPermission)。原版使用 LevelBasedPermissionSet 来检查查询的权限是否与当前的 PermissionLevel 匹配。由于通常会对一组权限检查权限集,因此可以通过 PermissionSet#union 将多个权限集组合成一个。它在功能上执行 OR 操作,意味着如果一个集合不检查某个权限,它应默认为 false

public interface ExamplePermissionSet extends PermissionSet {

    // 为我们的权限跟踪用户的状态
    int state();

    @Override
    default boolean hasPermission(Permission permission) {
        // 检查我们的权限
        if (permission instanceof HasExamplePermission example) {
            return this.state() >= example.state();
        }

        // 否则忽略
        return false;
    }
}

// 存储一个权限集
// 也可以在所需的目标上实现或存储
public static ExamplePermissionSet STATE_ONE = () -> 1;

// 检查权限集是否具有所需的权限
STATE_ONE.hasPermission(HAS_STATE_ONE);

目前,没有简单的方法在所需用户上存储自定义权限集。CommandSourceStack 确实有一个通过 withMaximumPermission 合并其他权限集的方法,但这需要在关联的 createCommandSourceStack 方法中处理。通常可以通过 permissions 方法查询普通的 LevelBasedPermissionSet,尽管对象之间没有公共接口,即使 PermissionSetSupplier 似乎为此目的而存在。

权限检查

现在,PermissionSet 永远不会直接在代码库中检查 Permission。这需要对象始终可访问。相反,会创建一个 PermissionCheck 对象,它接受 PermissionSetcheck 用户是否具有继续执行所需的数据。原版提供了两种类型的检查:$AlwaysPass,意味着它将始终返回 true;以及 $Require,要求集合具有所需的 Permission。这些检查也有一个用于转储命令报告的映射编解码器。

// 要求权限集具有管理员命令的访问权限
public static final PermissionCheck LEVEL_MODERATORS = new PermissionCheck.Require(COMMANDS_MODERATOR);

可以通过实现 check 的某个类或记录来创建自定义权限检查,并将映射编解码器注册到其静态注册表:

public static record AnyOf(List<Permission> permissions) implements PermissionCheck {
    public static final MapCodec<AnyOf> MAP_CODEC = Permission.CODEC.listOf().fieldOf("permissions")
        .xmap(AnyOf::new, AnyOf::permissions);

    @Override
    public boolean check(PermissionSet permissionSet) {
        return this.permissions.stream().filter(perm -> permissionSet.hasPermission(perm)).findAny().isPresent();
    }

    @Override
    public MapCodec<AnyOf> codec() {
        return MAP_CODEC;
    }
}

// 在某个注册处理程序中
Registry.register(
    BuiltInRegistries.PERMISSION_CHECK_TYPE
    Identifier.withNamespaceAndPath("examplemod", "any_of"),
    AnyOf.MAP_CODEC
);

// 存储检查以供在命令中使用
public static final PermissionCheck CHECK_STATE_ONE = new AnyOf(List.of(
    HAS_STATE_ONE,
    Permissions.COMMANDS_GAMEMASTER
));

// 对于某个命令
Commands.literal("example").requires(Commands.hasPermission(CHECK_STATE_ONE));
  • net.minecraft.client.multiplayer.ClientSuggestionProvider 不再实现 PermissionSource
    • 构造函数现在接受 PermissionSet 而不是 boolean
    • allowsRestrictedCommands -> ClientPacketListener#ALLOW_RESTRICTED_COMMANDS,现在是私有的,不是一对一
  • net.minecraft.client.player.LocalPlayer#setPermissionLevel -> setPermissions,不是一对一
  • net.minecraft.commands
    • Commands
      • LEVEL_* 现在是 PermissionCheck 而不是 int
      • hasPermission 现在接受 PermissionCheck 而不是 int,并返回 PermissionProviderCheck 而不是 PermissionCheck
      • createCompilationContext - 使用给定的权限创建源堆栈。
    • CommandSourceStack 不再实现 PermissionSource
      • 构造函数现在接受 PermissionSet 而不是 int
      • protected 构造函数现在是 private
      • withPermission 现在接受 PermissionSet 而不是 int
      • withMaximumPermission 现在接受 PermissionSet 而不是 int
    • ExecutionCommandSource 现在扩展 PermissionSetSupplier 而不是 PermissionSource
    • PermissionSource 接口已移除
    • SharedSuggestionProvider 现在扩展 PermissionSetSupplier
  • net.minecraft.commands.arguments.selector.EntitySelectorParser#allowSelectors 现在有一个接受 PermissionSetSupplier 的重载
  • net.minecraft.core.registries
    • BuiltInRegistries#PERMISSION_TYPERegistries#PERMISSION_TYPE - 一个定义某些数据需求的对象。
    • BuiltInRegistries#PERMISSION_CHECK_TYPERegistries#PERMISSION_CHECK_TYPE - 一个谓词,检查集合是否具有所需的数据。
  • net.minecraft.server
    • MinecraftServer
      • operatorUserPermissionLevel -> operatorUserPermissions,不是一对一
      • getFunctionCompilationLevel -> getFunctionCompilationPermissions,不是一对一
      • getProfilePermissions 现在返回 LevelBasedPermissionSet
    • ReloadableServerResources#loadResources 现在接受 PermissionSet 而不是 int
    • ServerFunctionLibrary 现在接受 PermissionSet 而不是 int
    • WorldLoader$InitConfig 现在接受 PermissionSet 而不是 int
  • net.minecraft.server.commands.PermissionCheck -> .server.permissions.PermissionCheck,不是一对一
  • net.minecraft.server.dedicated.DedicatedServerProperties
    • opPermissionLevel -> opPermissions,不是一对一
    • functionPermissionLevel -> functionPermissions,不是一对一
    • deserializePermissionsserializePermission - 读取和写入选定的级别权限集。
  • net.minecraft.server.jsonrpc.internalapi
    • MinecraftOperatorListService#op 现在接受一个可选的 PermissionLevel 而不是 int
    • MinecraftServerSettingsService
      • getOperatorUserPermissionLevel -> getOperatorUserPermissions,不是一对一
      • setOperatorUserPermissionLevel -> setOperatorUserPermissions,不是一对一
  • net.minecraft.server.jsonrpc.methods
    • OperatorService$OperatorDto#permissionLevel 现在接受一个可选的 PermissionLevel 而不是 int
    • ServerSettingsService
      • operatorUserPermissionLevel 现在返回 PermissionLevel 而不是 int
      • setOperatorUserPermissionLevel 现在接受并返回 PermissionLevel 而不是 int
  • net.minecraft.server.permissions
    • LevelBasedPermissionSet - 一组权限,检查用户是否具有相等或更高的命令权限级别。
    • Permission - 与用户权限相关的数据,例如命令级别。
    • PermissionCheckTypes - 原版提供的权限检查类型。
    • PermissionLevel - 定义权限的级别序列。
    • PermissionProviderCheck - 一个谓词,检查供应商的权限集与检查的匹配。
    • Permissions - 原版提供的权限。
    • PermissionSet - 一组用户拥有的权限,但主要定义一个方法来确定用户是否具有所需的权限。
    • PermissionSetSupplier - 一个提供 PermissionSet 的对象。
    • PermissionSetUnion - 多个权限集的联合。
    • PermissionTypes - 原版提供的权限类型。
  • net.minecraft.server.players
    • PlayersList#op 现在接受一个可选的 LevelBasedPermissionSet 而不是 int
    • ServerOpListEntry 现在接受 LevelBasedPermissionSet 而不是 int
      • getLevel -> permissions,不是一对一
  • net.minecraft.world.entity.player.Player#getPermissionLevelhasPermissions -> permissions,不是一对一
  • net.minecraft.world.entity.projectile.ProjectileUtils
    • getHitEntitiesAlong - 获取沿提供路径击中的实体。
    • getManyEntityHitResult - 获取沿两点之间路径在边界框内击中的所有实体。
  • net.minecraft.world.entity.projectile.arrow.AbstractArrow#findHitEntities - 获取被向量击中的所有实体。

新数据组件

随着矛的加入,添加了许多数据组件以提供相关功能。以下是对这些组件的简要概述。

使用效果

DataComponents#USE_EFFECTS 定义了一些效果,应用于正在使用(例如,右键单击)物品的玩家。目前,只有三种类型的效果:玩家在使用物品时是否可以冲刺、使用交互是否引起振动,以及应用于玩家水平移动的标量。

// 对于某个物品注册
new Item(new Item.Properties.component(
    DataComponents.USE_EFFECTS,
    new UseEffects(
        // 玩家在使用物品时是否可以冲刺
        true,
        // 是否在物品使用时从玩家处发送振动
        false
        // 应用于玩家水平移动的标量
        0.5f
    )
));

伤害类型

DataComponents#DAMAGE_TYPE 定义了用此物品击中实体时应用于实体的伤害类型。它接受伤害类型的 ResourceKeyDamageType 对象本身。

// 对于某个物品注册
new Item(new Item.Properties.component(
    DataComponents.DAMAGE_TYPE,
    new EitherHolder<>(
        // 此物品对攻击实体施加的伤害类型
        DamageTypes.FALLING_ANVIL
    )
));

挥动动画

DataComponents#SWING_ANIMATION 定义了使用物品挥动或攻击(例如,左键单击)时播放的动画。有三种类型的动画可以播放:SwingAnimationType#NONE,什么都不做;WHACK,播放标准的挥动动画;以及 STAB,播放矛的刺击动画。也可以指定动画的长度。

// 对于某个物品注册
new Item(new Item.Properties.component(
    DataComponents.SWING_ANIMATION,
    new SwingAnimation(
        // 要播放的动画
        SwingAnimationType.NONE,
        // 播放动画的时间,以刻为单位
        20
    )
));

最小攻击充能

DataComponents#MINIMUM_ATTACK_CHARGE 决定玩家在使用该物品进行另一次攻击之前必须等待多长时间。充能值介于 0 和 1 之间,决定了在另一次攻击之前等待延迟的百分比。延迟由玩家的攻击速度决定。如果玩家的动作是刺击,则检查两次。

// 对于某个物品注册
new Item(new Item.Properties.component(
    DataComponents.MINIMUM_ATTACK_CHARGE,
    // 玩家在使用此物品进行另一次攻击之前必须等待的时间百分比
    0.5f
));

攻击范围

DataComponents#ATTACK_RANGE 决定了当实体使用此物品攻击另一个实体时,可以攻击的范围。如果未设置,则默认为实体的交互范围属性。指定的范围适用于玩家,生物的攻击范围由范围乘以生物因子决定。当玩家处于创造模式时,也可以指定一个范围,覆盖默认范围。

// 对于某个物品注册
new Item(new Item.Properties.component(
    DataComponents.ATTACK_RANGE,
    new AttackRange(
        // 此物品击中实体的最小范围(以方块为单位)。
        // 必须在 [0, 64] 之间;默认为 0。
        0.4f,
        // 此物品击中实体的最大范围(以方块为单位)。
        // 必须在 [0,64] 之间;默认为 3。
        4.5f,
        // 此物品击中实体的最小范围(以方块为单位),
        // 前提是持有实体是处于创造模式的玩家。
        // 这取代了最小范围。
        // 必须在 [0, 64] 之间;默认为 0。
        0f,
        // 此物品击中实体的最大范围(以方块为单位),
        // 前提是持有实体是处于创造模式的玩家。
        // 这取代了最大范围。
        // 必须在 [0,64] 之间;默认为 3。
        5f,
        // 用于膨胀碰撞箱的边距(以方块为单位),
        // 补偿潜在的精度问题。
        // 必须在 [0,1] 之间;默认为 0.3。
        0.25f,
        // 乘以最小和最大范围的标量,以确定
        // 非玩家实体的触及范围。
        // 必须在 [0,2] 之间;默认为 1。
        1.1f
    )
));

穿刺武器

DataComponents#PIERCING_WEAPON 将玩家的攻击设置为不是攻击,而是刺击或穿刺攻击。这是一个与挥动不同的动作,后者要么攻击实体,要么破坏方块。穿刺武器可以攻击实体,但无法破坏方块。它也会对冲刺应用任何附魔效果。穿刺武器仅适用于玩家。

逻辑流程如下:

  • 如果 Player#cannotAttackWithItem 返回 true,则终止流程
  • 穿刺攻击通过以下方式处理:
    • 客户端 - MultiPlayerGameMode#piercingAttack
    • 服务器 - PiercingWeapon#attack
  • 仅限服务器:
    • 获取所有满足以下条件的实体:
      • 在实体的攻击范围内 DataComponents#ATTACK_RANGE
      • 在从玩家眼睛位置开始构建的碰撞箱内
      • 如果 PiercingWeapon#canHitEntity 返回 true:
        • 玩家不是无敌或死亡,并且
        • 要么:
          • 实体是 Interaction 实体
        • 或者:
          • 实体可以被投射物击中
          • 如果双方都是玩家,则此玩家可以伤害对方玩家
          • 不是同一载具的乘客
    • 对每个实体调用 LivingEntity#stabAttack
  • 触发 LivingEntity#onAttack
  • 触发 LivingEntity#lungeForwardMaybe
  • 仅限服务器:
    • 如果至少击中了一个实体,则播放 PiercingWeapon#makeHitSound
    • 播放 PiercingWeapon#makeSound
  • 触发 LivingEntity#swing
// 对于某个物品注册
new Item(new Item.Properties.component(
    DataComponents.PIERCING_WEAPON,
    new PiercingWeapon(
        // 被此物品击中是否会对实体造成击退。
        true,
        // 被此物品击中是否会使实体从载具上下来。
        true,
        // 使用此物品攻击时播放的声音。
        // 如果 optional 为空,则不播放声音。
        Optional.of(SoundEvents.LLAMA_SWAG),
        // 此物品击中实体时播放的声音。
        // 如果 optional 为空,则不播放声音。
        Optional.of(SoundEvents.ITEM_BREAK)
    )
));

动能武器

DataComponents#KINETIC_WEAPON 影响实体的使用(例如,右键单击)行为。在右键单击时,如果物品具有该组件,则每刻调用 KineticWeapon#damageEntities 而不是 Item#onUseTick,仅在服务器上。动能武器也会调用 LivingEntity#stabAttack 来伤害其实体,类似于穿刺攻击。实际上,该组件本身与 PiercingWeapon 类似,只是多了几个字段来处理应用的动能伤害,并使其适用于所有活体实体而不仅仅是玩家。

要使刺击攻击发生,必须满足其中一个条件(下马、击退、伤害)并返回 true。攻击范围从 DataComponents#ATTACK_RANGE 组件获得。如果发生刺击攻击,则会在服务器上触发 SPEAR_MOBS_TRIGGER 条件。

// 对于某个物品注册
new Item(new Item.Properties.component(
    DataComponents.KINETIC_WEAPON,
    new KineticWeapon(
        // 此实体在尝试接触(例如,伤害)另一个实体之前等待的刻数。
        10,
        // 在尝试刺击范围内的任何实体之前等待的刻数。
        20,
        // 检查此物品的攻击是否会使载具中的实体下马的条件。
        // 如果 optional 不存在,则默认为 false。
        Optional.of(new KineticWeapon.Condition(
            // 从此条件可能返回 true 的首次使用加延迟的最大刻数。
            100,
            // 此条件成功所需的实体移动的最小速度。
            // 速度计算为增量运动与视图向量的点积乘以 20。
            // 原版矛对下马使用 7-14 的值,对击退使用 5.1。
            9f,
            // 此条件成功所需的,相对于攻击实体的此实体的最小移动速度。
            // 原版矛对伤害使用 4.6。
            5f
        )),
        // 检查此物品的攻击是否会对实体造成击退的条件。
        // 如果 optional 不存在,则默认为 false。
        Optional.of(KineticWeapon.Condition.ofAttackerSpeed(
            // 最大刻数
            100,
            // 实体移动速度
            5.1f
        )),
        // 检查此物品的攻击是否会伤害实体的条件。
        // 如果 optional 不存在,则默认为 false。
        Optional.of(KineticWeapon.Condition.ofRelativeSpeed(
            // 最大刻数
            100,
            // 相对移动速度
            4.6f
        )),
        // 第三人称攻击动画期间物品的移动
        // 原版矛使用 0.38。
        0.38f,
        // 应用于实体伤害的乘数
        // 伤害计算为此实体相对于其目标的相对移动速度。
        4f,
        // 首次使用此物品时播放的声音。
        // 如果 optional 为空,则不播放声音。
        Optional.of(SoundEvents.LLAMA_SWAG),
        // 此物品击中实体时播放的声音。
        // 如果 optional 为空,则不播放声音。
        Optiona.of(SoundEvents.ITEM_BREAK)
    )
));
  • net.minecraft.core.components
    • DataComponents
      • USE_EFFECTS - 使用物品时应用于实体的效果。
      • MINIMUM_ATTACK_CHARGE - 使用物品攻击的最短时间。
      • DAMAGE_TYPE - 物品造成的 DamageType
      • PIERCING_WEAPON - 一种具有某些碰撞箱范围并向实体冲刺的武器。
      • KINETIC_WEAPON - 一种需要一定前进动量的具有碰撞箱范围的武器。
      • SWING_ANIMATION - 挥动物品时应用的动画。
      • ATTACK_RANGE - 使用物品时设置自定义攻击范围,覆盖正常的实体交互范围。
  • net.minecraft.core.component.DataComponentType#ignoreSwapAnimation$Builder#ignoreSwapAnimation - 当为 true 时,交换动画不会影响数据组件的“使用”。
  • net.minecraft.core.component.predicates
    • AnyValue - 一个谓词,检查获取器上是否存在该组件。
    • DataComponentPredicate
      • $Type 现在是一个接口
        • 其原始实现已被 $TypeBase 取代
      • $AnyValueType - 一个使用 AnyValue 谓词的类型。
      • $ConcreteType - 一个定义特定谓词的类型。
  • net.minecraft.network.protocol.game.ServerboundInteractPacket#isWithinRange - 玩家的交互是否在有效范围内以执行。
  • net.minecraft.world.entity
    • LivingEntity
      • SWING_DURATION -> SwingAnimation#duration,不是一对一
      • stabbedEntities - 最近被动能武器攻击的实体数量。
      • entityAttackRange - 此实体可以攻击的范围。
      • getActiveItem - 当前使用的物品,或主手物品。
    • Mob
      • chargeSpeedModifier - 冲刺时应用于移动速度的修改器。
      • canFireProjectileWeapon -> canUseNonMeleeWeapon,现在接受 ItemStack 而不是 ProjectileWeaponItem
      • getAttackBoundingBox 现在接受一个水平膨胀偏移
  • net.minecraft.world.entity.ai.behavior
    • ChargeAttack - 处理生物执行的冲刺攻击。
    • SpearApproach - 当持有动能武器时接近敌人。
    • SpearAttack - 使用动能武器攻击敌人。
    • SpearRetreat - 使用动能武器后从攻击目标逃跑。
  • net.minecraft.world.entity.ai.goal.SpearUseGoal - 处理生物使用矛。
  • net.minecraft.world.entity.ai.memory.MemoryModuleType
    • SPEAR_FLEEING_TIME - 使用动能武器后实体已逃跑的刻数。
    • SPEAR_FLEEING_POSITION - 使用动能武器后实体逃跑到的位置。
    • SPEAR_CHARGE_POSITION - 使用动能武器时实体冲刺到的位置。
    • SPEAR_ENGAGE_TIME - 使用动能武器时此实体与敌人交战的时间。
    • SPEAR_STATUS - 使用动能武器时实体的状态。
  • net.minecraft.world.entity.player.Player
    • hasEnoughFoodToDoExhaustiveManoeuvres - 返回玩家是否可以进行消耗体力的机动。
    • canInteractWithEntity -> isWithinEntityInteractionRange
    • isWithinAttackRange - 被瞄准的边界框是否在玩家的范围内。
    • canInteractWithBlock -> isWithinBlockInteractionRange
    • CREATIVE_ENTITY_INTERACTION_RANGE_MODIFIER_VALUE - 一个修饰符,将交互的最大范围增加给定的数量。
  • net.minecraft.world.item
    • Item#getDamageSource -> getItemDamageSource,现已弃用
    • ItemStack
      • getSwingAnimation - 返回物品的挥动动画。
      • getDamageSource - 返回物品被击中时提供的伤害来源。
      • causeUseVibration - 如果使用中的物品可以引起振动,则发送游戏事件。
    • SwingAnimationType - 挥动物品时播放的动画类型。
  • net.minecraft.world.item.component
    • AttackRange - 此物品的碰撞箱范围。
    • KineticWeapon - 一种需要一定前进动量的武器。
    • PiercingWeapon - 一种向实体冲刺的武器。
    • SwingAnimation - 挥动物品时应用的动画。
    • UseEffects - 使用物品时应用于实体的效果。

环境属性的时间线

环境属性,顾名思义,为给定的维度(dimension)和/或生物群系(biome)(统称为“环境”)定义了一组属性或修改(“attributes”)。它们直接存储在生物群系或维度类型的 attributes 字段下,或作为可变时间线下 tracks 字段的一部分。每个属性可以代表从视觉设置到游戏行为的任何内容,在不同值之间进行插值。原版在 EnvironmentAttributes 中提供了它们可用的属性,而存储的属性则从 Level#environmentAttributes 获得。

// 对于某个 DimensionType json
// 在 `data/examplemod/dimension_type/example_dimension.json`
{
    // 定义在维度内应用的属性
    "attributes": {
        // 设置云高度
        // 更技术地说,通过覆盖来修改值
        "minecraft:visual/cloud_height": 90
    },
    // ...
}

// 对于某个 Biome json
// 在 `data/examplemod/worldgen/biome/example_biome.json`
{
    // 定义在生物群系内应用的属性
    // 默认或修改维度中的属性
    // 这些属性必须是位置性的
    "attributes": {
        "minecraft:visual/cloud_height": {
            // 不设置值,而是应用一个修改器
            "modifier": "add",
            // 将 60 加到 90,使该生物群系的云高度为 150
            "argument": 60
        }
    }
    // ...
}

// 对于某个 Timeline json
// 在 `data/examplemod/timeline/example_timeline.json
{
    // 此轨道在重复之前花费的刻数
    "period_ticks": 24000,
    // 定义要基于定义的
    // 关键帧进行插值的属性。
    // 默认或修改生物群系或维度中的属性
    "tracks": {
        "minecraft:visual/cloud_height": {
            // 定义属性特定值的关键帧
            "keyframes": [
                {
                    // 表示关键帧的刻
                    "tick": 12000,
                    // 修改值的参数
                    // 在这种情况下,将 1 加到 60 + 90,使云高度为 151
                    "value": 1
                },
                {
                    // 表示关键帧的刻
                    "tick": 23999,
                    // 修改值的参数
                    // 在这种情况下,将 0 加到 60 + 90,使云高度为 150
                    "value": 0
                }
            ],
            // 不设置值,而是将修改器应用于参数
            "modifier": "add",
            // 在刻之间进行插值时应用的采样函数
            "ease": "linear"
        }
    }
}

当调用 EnvironmentAttributeSystem#getValue 时,属性值通过 Level 定义的层获得:

  1. 从注册的属性中读取默认值(通过 EnvironmentAttribute#defaultValue)。
  2. 应用来自维度的修改器,如果该属性不存在则不执行任何操作。
  3. 应用来自生物群系的修改器,如果不存在则不执行任何操作。
  4. 应用 DimensionType 中定义的所有活动时间线的修改器,如果不存在则不执行任何操作。时间线顺序不保证。
  5. 如果维度可以有天气(天空光照、无天花板、且不是末地),则应用 WeatherAttributes 的修改器。
  6. 如果在客户端(即 ClientLevel),则应用天空闪光修改器。
  7. 将最终值清理到 EnvironmentAttribute 定义的范围内。

这是高度简化的,并引入了许多新概念,因此让我们通过创建我们自己的环境属性和时间线来进一步分解。

自定义环境属性

环境属性通过 $Builder 创建,使用 EnvironmentAttribute#builder,接受其表示的类型值(例如,浮点数、整数、对象)。构建器只需要设置一个值:defaultValue。如果维度或生物群系未覆盖该属性,则使用此值。如果属性值应具有一组有效的状态,则可以通过 valueRange 设置 AttributeRangeAttributeRange 基本上是一个一元运算符,通过 sanitize 将输入转换为其“有效”状态。它还通过 validate 验证通过 JSON 传入的值是否处于“有效”状态。

从那里开始,还有三个方法负责确定用于计算值的逻辑。$Builder#syncable 将属性同步到客户端,这对于任何导致某种变化的属性(例如,视觉、音频或通用代码)是必需的。notPositional 意味着该属性不能应用于生物群系(仍可在维度或时间线中设置),否则会抛出异常。最后,spatiallyInterpolated 将尝试使用属性类型在不同的生物群系之间进行插值,以应用更无缝的过渡。原版仅处理客户端属性的空间插值。服务器上的任何内容都必须处理自己的 SpatialAttributeInterpolator

最后,实际属性可以通过 $Builder#build 获得。该值必须注册到 BuiltInRegistries#ENVIRONMENT_ATTRIBUTE

public static final EnvironmentAttribute<Boolean> EXAMPLE_ATTRIBUTE = Registry.register(
    BuiltInRegistries.ENVIRONMENT_ATTRIBUTE,
    Identifier.withNamespaceAndPath("examplemod", "example_attribute"),
    EnvironmentAttribute.builder(
        // 属性类型
        // 必须与属性值的泛型匹配
        AttributeTypes.BOOLEAN
    )
        // 此属性应默认具有的值
        .defaultValue(false)
        // 将此值同步到客户端
        .syncable()
        .build()
);
// 对于某个 DimensionType json
// 在 `data/examplemod/dimension_type/example_dimension.json`
{
    "attributes": {
        "examplemod:example_attribute": true
    },
    // ...
}

// 对于某个 Biome json
// 在 `data/examplemod/worldgen/biome/example_biome.json`
{
    "attributes": {
        "examplemod:example_attribute": {
            "modifier": "xor",
            "argument": true
        }
    }
    // ...
}

// 对于某个 Timeline json
// 在 `data/examplemod/timeline/example_timeline.json
{
    "period_ticks": 24000,
    "tracks": {
        "examplemod:example_attribute": {
            "keyframes": [
                {
                    "tick": 12000,
                    "value": false
                },
                {
                    "tick": 23999,
                    "value": true
                }
            ],
            "modifier": "and",
            "ease": "linear"
        }
    }
}

自定义属性类型

每个环境属性都有一个关联的属性类型,静态注册到 BuiltInRegistries#ATTRIBUTE_TYPE。这不仅定义了如何序列化对象值,还包含可以应用于值的修改以及如何在空间和帧之间进行插值。实际上,包括 syncablespatiallyInterpolated 在内的所有构建器设置都依赖于属性类型来确定执行该操作意味着什么。如果没有它,甚至无法从维度或生物群系 JSON 中读取属性,更不用说获取属性值的实际逻辑了。

因此,属性类型可以分为三个部分:序列化编解码器、修改器库和插值函数。

// 我们将使用此示例对象来解释属性类型
public record ExampleObject(int value1, boolean value2) {
    // 默认值
    public static final ExampleObject DEFAULT = new ExampleObject(0, false);
}

类型序列化

属性类型的序列化通过该类型的编解码器处理,包括到磁盘(生物群系和维度 JSON)和网络($Builder#syncable):

// 用于序列化属性类型值的编解码器
public static final Codec<ExampleObject> CODEC = RecordCodecBuilder.create(
    instance -> instance.group(
        Codec.INT.fieldOf("value1").forGetter(ExampleObject::value1),
        Codec.BOOL.fieldOf("value2").forGetter(ExampleObject::value2)
    ).apply(instance, ExampleObject::new)
);

修改器库

修改器库是一个 AttributeModifier$OperationIdAttributeModifier 的映射,确定可以对默认值执行哪些操作。如果映射不包含任何操作,则默认值不能更改。AttributeType 的所有静态构造函数都添加了 OVERRIDE 修改器,允许维度和/或生物群系设置值。这个映射应该被视为一个伪注册表(基本上是键到唯一值的映射),因为用于序列化的默认编解码器是通过 id 解析器为 BiMap 提供的。

一个 AttributeModifier 定义了两个泛型:第一个是环境属性值类型,第二个是用于应用操作的任意对象。修改器有两个方法:apply,接受值和参数以返回一个新值;以及 argumentCodec,用于正确序列化参数。对于任何操作,所有可能的修改都必须实现在单个 AttributeModifier 中:

// 仅处理对象一部分的修改器
public static final AttributeModifier<ExampleObject, Integer> ADD = new AttributeModifier<>() {

    @Override
    public ExampleObject apply(ExampleObject subject, Integer argument) {
        // 将操作应用于 subject
        return new ExampleObject(subject.value1() + argument, subject.value2());
    }

    @Override
    public Codec<Integer> argumentCodec(EnvironmentAttribute<ExampleObject> attribute) {
        // 构造用于反序列化参数的编解码器
        return Codec.INT;
    }
};

public static final AttributeModifier<ExampleObject, Boolean> OR = new AttributeModifier<>() {

    @Override
    public ExampleObject apply(ExampleObject subject, Boolean argument) {
        // 将操作应用于 subject
        return new ExampleObject(subject.value1(), subject.value2() || argument);
    }

    @Override
    public Codec<Boolean> argumentCodec(EnvironmentAttribute<ExampleObject> attribute) {
        // 构造用于反序列化参数的编解码器
        return Codec.BOOL;
    }
};

// 一个处理所有可能对象组合的修改器
public static final AttributeModifier<ExampleObject, Either<ExampleObject, Either<Integer, Boolean>>> AND = new AttributeModifier<>() {

    @Override
    public ExampleObject apply(ExampleObject subject, Either<ExampleObject, Either<Integer, Boolean>> argument) {
        return argument.map(
            arg -> new ExampleObject(subject.value1() & arg.value1(), subject.value2() && arg.value2()),
            either -> either.map(
                arg -> new ExampleObject(subject.value1() & arg, subject.value2()),
                arg -> new ExampleObject(subject.value1(), subject.value2() && arg)
            )
        );
    }

    @Override
    public Codec<Either<ExampleObject, Either<Integer, Boolean>>> argumentCodec(EnvironmentAttribute<ExampleObject> attribute) {
        // 构造用于反序列化参数的编解码器
        // 我们可以为值类型使用属性编解码器
        return Codec.either(attribute.valueCodec(), Codec.either(Codec.INT, Codec.BOOL));
    }
};

// 构造库
// 参数可以是任何值,只要它可以被序列化和处理
// 如果使用属性类型的静态构造函数之一,则会自动添加覆盖
// 处理程序以及映射的关联修改器编解码器
public static final Map<AttributeModifier.OperationId, AttributeModifier<ExampleObject, ?>> EXAMPLE_LIBRARY = Map.of(
    AttributeModifier.OperationId.ADD, ADD,
    AttributeModifier.OperationId.OR, OR,
    AttributeModifier.OperationId.AND, AND
);

类型插值

为了支持插值,无论是对于客户端帧(由于 $Builder#syncable)、空间($Builder#spatiallyInterpolated)、状态(天气)还是关键帧(时间线),都需要一个函数,在给定 0 和 1 之间的某个步长(时间或位置)时,如何合并两个值。这通过 LerpFunction 处理,其泛型是环境属性值类型。对于非插值值,这通常使用 LerpFunction#ofStep,它类似于两个值之间的简单阈值。更具体地说,空间插值将阈值设置为 0.5,而部分刻、关键帧和状态更改将仅考虑完整步长(意味着总是下一个值)。然而,这个函数可以根据您的选择定义:

// Step 表示 0 和 1 之间的插值
// Original 表示步长为 0 的值
// Next 表示步长为 1 的值
public static final LerpFunction<ExampleObject> EXAMPLE_SPATIAL_LERP = (step, original, next) -> {
    return new ExampleObject(
        Mth.lerp(step, original.value1(), next.value1()),
        step >= 0.5f ? next.value2() : original.value2()
    );
}

public static final LerpFunction<ExampleObject> EXAMPLE_PARTIAL_LERP = (step, original, next) -> {
    return new ExampleObject(
        Mth.lerp(step, original.value1(), next.value1()),
        next.value2()
    );
}

// 将始终返回第一个值
public static final LerpFunction<ExampleObject> EXAMPLE_KEYFRAME_LERP = LerpFunction.ofConstant();

// 在步长过去 0.1 后更改为下一个状态
public static final LerpFunction<ExampleObject> EXAMPLE_STATE_CHANGE_LERP = LerpFunction.ofStep(0.1f);

整合在一起

有了这些部分,现在可以构造一个 AttributeType。这通常使用静态构造函数之一完成:ofInterpolated 用于定义其插值函数的值,或 ofNotInterpolated 用于可以在两个值之间直接切换的值。对于常见用例,除非您的值在玩家自然可见的内容(例如,雾或天空颜色的视觉)之间过渡,否则插值通常是不必要的。

如果您决定改用 AttributeType 实例构造函数,您还需要创建一个编解码器来序列化修改器映射。请参阅 AttributeType#createModifierCodec 了解如何操作。

// 属性类型必须静态注册才能被正确处理
public static final AttributeType<ExampleObject> EXAMPLE_ATTRIBUTE_TYPE = Registry.register(
    BuiltInRegistries.ATTRIBUTE_TYPE,
    Identifier.withNamespaceAndPath("examplemod", "example_attribute_type"),
    new AttributeType<>(
        // 值的编解码器
        ExampleObject.CODEC,
        // 可以修改的操作映射
        // `OVERRIDE` 会自动添加用于序列化
        EXAMPLE_LIBRARY,
        // 用于序列化修改器库的编解码器
        Util.make(() -> {
            ImmutableBiMap<AttributeModifier.OperationId, AttributeModifier<Value, ?>> map = ImmutableBiMap.builder()
                .put(AttributeModifier.OperationId.OVERRIDE, AttributeModifier.override())
                .putAll(EXAMPLE_LIBRARY)
                .buildOrThrow();
            return ExtraCodecs.idResolverCodec(AttributeModifier.OperationId.CODEC, map::get, map.inverse()::get);
        }),
        // 在时间线中两个关键帧之间插值的函数
        EXAMPLE_KEYFRAME_LERP,
        // 在两个状态之间插值的函数(仅用于天气映射中的属性)
        EXAMPLE_STATE_CHANGE_LERP,
        // 在两个空间坐标之间插值的函数
        EXAMPLE_SPATIAL_LERP,
        // 在客户端帧之间插值的函数
        EXAMPLE_PARTIAL_LERP
    )
);

从那里,我们可以创建一个使用该类型的 EnvironmentAttribute

public static final EnvironmentAttribute<ExampleObject> EXAMPLE_OBJECT_ATTRIBUTE = Registry.register(
    BuiltInRegistries.ENVIRONMENT_ATTRIBUTE,
    Identifier.withNamespaceAndPath("examplemod", "example_object_attribute"),
    EnvironmentAttribute.builder(
        EXAMPLE_ATTRIBUTE_TYPE
    )
        .defaultValue(ExampleObject.DEFAULT)
        // 由于编解码器和部分刻插值而可能
        .syncable()
        // 由于空间插值而可能
        .spatiallyInterpolated()
        .build()
);
// 对于某个 DimensionType json
// 在 `data/examplemod/dimension_type/example_dimension.json`
{
    "attributes": {
        "examplemod:example_object_attribute": {
            "value1": 10,
            "value2": true
        }
    },
    // ...
}

// 对于某个 Biome json
// 在 `data/examplemod/worldgen/biome/example_biome.json`
{
    "attributes": {
        "examplemod:example_object_attribute": {
            // 必须使用库中定义的参数之一
            // 在这种情况下是 'add'、'or' 或 'and'
            "modifier": "and",
            // 这可以是布尔值、整数或对象
            // 因为序列化器是这样定义的
            "argument": false
        }
    }
    // ...
}

// 对于某个 Timeline json
// 在 `data/examplemod/timeline/example_timeline.json
{
    "period_ticks": 24000,
    "tracks": {
        "examplemod:example_object_attribute": {
            "keyframes": [
                {
                    "tick": 12000,
                    // 这可以是布尔值、整数或对象
                    // 因为序列化器是这样定义的
                    "value": 1
                },
                {
                    "tick": 23999,
                    // 这可以是布尔值、整数或对象
                    // 因为序列化器是这样定义的
                    "value": {
                        "value1": 0,
                        "value2": false
                    }
                }
            ],
            // 必须使用库中定义的参数之一
            // 在这种情况下是 'add'、'or' 或 'and'
            "modifier": "and",
            "ease": "linear"
        }
    }
}

时间线

Timeline 是一种基于当前游戏时间修改属性的方法。更具体地说,它们定义了一些关键帧,值在关键帧之间进行插值,首先使用 EasingType 函数确定步长,其次使用 AttributeType#keyframeLerp 获取值。这不仅是大脑中 Schedule 的替代品,也是与昼夜循环相关的属性(例如,天空颜色、史莱姆生成几率等)的替代品。它们作为生物群系修改器之后的一层,用于位置性和非位置性属性。

时间线基于 DimensionType#timelines 标签激活,这些标签以 in_ 为前缀(例如,minecraft:in_overworld 是主世界的时间线标签)。所有维度标签都包括 minecraft:universal 标签,这意味着所有标记的时间线将在所有维度内运行(前提是它们添加了 universal 标签)。

原版时间线如下:

  • minecraft:day: 昼夜循环
  • minecraft:moon: 月相和生成几率
  • minecraft:villager_schedule: 村民执行什么 Activity
  • minecraft:early_game: 在最初几天阻止掠夺者巡逻队生成

关联的标签如下:

  • minecraft:universal
    • minecraft:villager_schedule
  • minecraft:in_overworld - 主世界维度
    • #minecraft:universal
    • minecraft:day
    • minecraft:moon
    • minecraft:early_game
  • minecraft:in_nether - 下界维度
    • #minecraft:universal
  • minecraft:in_end - 末地维度
    • #minecraft:universal

关键帧

每个 Timeline 由关键帧组成,负责确定在给定刻时修改器的参数应该是什么。然后,这些关键帧被编译成一个称为 KeyframeTrack 的列表,在构造属性层时烘焙成一个 KeyframeTrackSampler。每两个相邻的关键帧(包括第一个和最后一个)被认为是一个 KeyframeTrackSampler$Segment。这就是用于在给定刻采样属性的内容。

假设我们有以下(关键帧,值)段 (100, 0) -> (200, 1),并且我们当前在 150 刻。我们如何选择使用什么参数?这通过两个操作执行。首先,我们计算步长:介于 01 之间的值,决定与值进行多少插值。步长首先线性计算:(current_tick - start_segment_tick) / (end_segment_tick - start_segment_tick)。然后,将步长传递给所需的 EasingType,这是一个接受 0-1 值并返回 0-1 值的函数,例如 in_out_bounceout_back。您也可以像这样创建自己的 EasingType

// `EasingType#registerSimple` 必须设为公开
EasyingType.registerSimple(
    // 函数的名称
    "examplemod:ease",
    // 应用于值的函数
    // 对于平滑过渡,函数应将 0 -> 0 和 1 -> 1
    original -> 0.5f * (float) Mth.sin(Math.PI * (3 * original - 0.5)) + 0.5f
);

然后,它将步长与两个参数一起传递给 AttributeType#keyframeLerp 函数,以获得要应用的插值参数。

属性轨道

通过确定参数的关键帧,我们通过一个 AttributeTrack 将参数应用于属性,在构造属性层时烘焙成一个 AttributeTrackSampler。一个 AttributeTrack 包含获取参数的 KeyframeTrack,以及将参数应用于值的 ArgumentModifier。请注意,对于给定的轨道只能有一个修改器。

这些 AttributeTrack 然后存储在一个属性到轨道的映射中,这定义了我们的 Timeline。时间线还包含一个可选的整数,表示轨道的周期。这里的“period”充当时间线中所有轨道的一次完整运行。超出周期的值取模。大多数时间线使用 24000 作为周期,因为这代表 Minecraft 一天中的刻数。

自定义时间线

自定义 Timeline 被添加到 timeline 数据包注册表:

// 对于某个 Timeline json
// 在 `data/examplemod/timeline/example_timeline.json
{
    // 每 3000 刻运行一次(一天的 1/8)
    "period_ticks": 3000,
    "tracks": {
        // 要修改的属性
        "examplemod:example_object_attribute": {
            // 确定参数之间步长的缓动函数
            "ease": "examplemod:ease",
            // 定义在设置刻的参数的关键帧列表
            // 然后使用缓动函数和关键帧插值对参数进行插值
            "keyframes": [
                {
                    // 此参数为给定值的刻
                    "tick": 1500,
                    // 将 10 加到属性
                    "value": 10
                },
                // 在中间,使用缓动函数在 10 和 0 之间逐步下降
                {
                    "tick": 2999,
                    // 将 0 加到属性
                    "value": 0
                }
                // 在中间,使用缓动函数在 0 和 10 之间逐步上升
            ],
            // 将参数应用于值时要使用的修改器
            "modifier": "add"
        }
    }
}
  • net.minecraft.client
    • Camera#attributeProbe - 获取客户端环境属性探测器的值和插值。
    • Minecraft
      • getSituationalMusic 现在返回 Music 而不是 MusicInfo
      • getMusicVolume - 获取背景音乐的音量,如果打开的屏幕有背景音乐则获取正常音量。
  • net.minecraft.client.multiplayer.ClientLevel
    • effects 已移除
    • getSkyDarken -> EnvironmentAttributes#SKY_LIGHT_COLORSKY_LIGHT_FACTOR;不是一对一
    • getSkyColor -> EnvironmentAttributes#SKY_COLOR,不是一对一
    • getCloudColor -> EnvironmentAttributes#CLOUD_COLOR,不是一对一
    • getStarBrightness -> EnvironmentAttributes#STAR_BRIGHTNESS,不是一对一
    • getSkyFlashTime 现在是私有的
  • net.minecraft.client.renderer
    • DimensionSpecialEffects 类已移除,完全被 EnvironmentAttribute 取代
    • SkyRenderer
      • renderSkyDisc 现在接受一个 ARGB int 而不是三个 RGB float
      • renderSunMoonAndStars 现在接受两个额外的 float 用于月亮和星星的旋转
  • net.minecraft.client.renderer.state.SkyRenderState
    • skyType -> skybox,不是一对一
    • isSunriseOrSunsettimeOfDay 已移除
    • moonAnglestarAngle - 月亮和星星的角度。
  • net.minecraft.client.resources.sounds.BiomeAmbientSoundsHandler 不再接受 BiomeManager
  • net.minecraft.client.sounds
    • MusicInfo -> Minecraft#getSituationalMusicgetMusicVolume;不是一对一
    • MusicManager#startPlaying 现在接受 Music 而不是 MusicInfo
  • net.minecraft.core.registries
    • BuiltInRegistriesRegistries#ENVIRONMENT_ATTRIBUTE - 环境属性的注册表。
    • BuiltInRegistriesRegistries#ATTRIBUTE_TYPE - 属性类型的注册表。
    • BuiltInRegistiresRegistries#SCHEDULE 已移除
    • Registries#TIMELINE - 时间线的注册表键。
  • net.minecraft.data.tags.TimelineTagsProvider - 时间线的标签提供者。
  • net.minecraft.server.level.ServerLevel#getMoonBrightness - 返回月亮的亮度。
  • net.minecraft.sounds.Music#event -> sound
  • net.minecraft.tags.TimelineTags - 时间线的标签。
  • net.minecraft.util
    • BinaryAnimator$EasingFunction -> EasingType
    • CubicSampler -> GaussianSamplerSpatialAttributeInterpolator;不是一对一
    • KeyframeTrack - 一个关键帧轨道以及它们之间执行的缓动。
    • KeyframeTrackSampler - 一个基于周期重播的关键帧轨道,使用提供的函数在值之间进行插值。
  • net.minecraft.world.attribute
    • AmbientSounds - 在环境中环境播放的声音。
    • AttributeRange - 一个接口,用于验证输入并将相应值清理到适当的边界。
    • AttributeType - 属性可以执行的操作和修改的类型定义。
    • AttributeTypes - 所有原版属性类型的注册表。
    • BackgroundMusic - 在环境中播放的背景音乐。
    • BedRule - 环境中床的功能规则。
    • EnvironmentAttribute - 环境中某个属性的定义。
    • EnvironmentAttributeLayer - 一个修改值的层。
    • EnvironmentAttributeMap - 属性定义到其参数和修改器的映射。
    • EnvironmentAttributeProbe - 用于获取和插值值的属性处理程序。仅由相机使用。
    • EnvironmentAttributeReader - 一个可以通过维度或位置查找环境属性的读取器。
    • EnvironmentAttributes - 所有原版环境属性的注册表。
    • EnvironmentAttributeSystem - 一个获取和空间插值环境属性的读取器实现。
    • LerpFunction - 一个函数式接口,接受 0-1 之间的某个值以及起始和结束值以在之间进行插值。
    • WeatherAttributes - 用于应用天气层的属性映射。
  • net.minecraft.world.attribute.holder
    • AttributeModifier - 一个修改器,接受属性值以及某个参数(通常是相同类型的值)以产生修改后的值。
    • BooleanModifier - 带有布尔参数的布尔值修改器。
    • ColorModifier - 带有某个参数(通常是整数)的 ARGB 整数修改器。
    • FloatModifier - 带有某个参数(通常是浮点数或带有 alpha 插值器的浮点数)的浮点数修改器。
    • FloatWithAlpha - 一个包含某个值和通常用于混合的 alpha 的记录。
  • net.minecraft.world.entity.ai.Brain
    • getSchedule 已移除
    • setSchedule 现在接受 EnvrionmentAttribute<Activity> 而不是 Schedule
    • updateActivityFromSchedule 现在接受 EnvironmentAttributeSystem 和位置而不是白天时间
  • net.minecraft.world.entity.animal.bee.Bee#isNightOrRainingEnvironmentAttributes#BEES_STAY_IN_HIVE 取代
  • net.minecraft.world.entity.player.Player$BedSleepingProblem 现在是一个记录
    • NOT_POSSIBLE_HERE -> BedRule#EXPLODES
    • NOT_POSSIBLE_NOW -> BedRule#CAN_SLEEP_WHEN_DARK
  • net.minecraft.world.entity.schedule
    • Keyframe -> .minecraft.util.Keyframe,不是一对一
    • Schedule 已移除,其逻辑被 TimelineTimelines 取代
    • ScheduleBuilder 已移除,其逻辑被 Timeline$Builder 取代
    • Timeline -> .world.timeline.Timeline,不是一对一
  • net.minecraft.world.entity.variant.SpawnContext 现在接受 EnvironmentAttributeReader
  • net.minecraft.world.level
    • Level
      • isMoonVisibleEnvironmentAttributes#MOON_ANGLE 取代
      • getSunAngleEnvironmentAttributes#SUN_ANGLE 取代
      • canHaveWeather 现在是 public
    • LevelAccessor 现在实现 LevelReader 而不是 LevelTimeAccess
    • LevelReader#environmentAttributes - 返回管理器,用于获取维度及其关联生物群系内的环境属性。
    • LevelTimeAccess 接口已移除
    • MoonPhase
      • CODEC - 月相的编解码器。
      • PHASE_LENGTH - 月相存在的刻数。
      • startTick - 特定相位的开始刻。
  • net.minecraft.world.level.biome
    • AmbientAdditionsSettings -> .world.attribute.AmbientAdditionsSettings
    • AmbientMoodSettings -> .world.attribute.AmbientMoodSettings
    • AmbientParticleSettings -> .world.attribute.AmbientParticle
    • Biome 现在接受 EnvironmentAttributeMap
      • getSkyColor -> EnvironmentAttributes#SKY_COLOR
      • getFogColor -> EnvironmentAttributes#FOG_COLOR
      • getAttributes - 获取此生物群系的属性。
      • getWaterFogColor -> EnvironmentAttributes#WATER_FOG_COLOR
      • getAmbientParticle -> EnvironmentAttributes#AMBIENT_PARTICLES
      • getAmbientLoop -> AmbientSounds#loop 环境属性
      • getAmbientMood -> AmbientSounds#mood 环境属性
      • getAmbientAdditions -> AmbientSounds#additions 环境属性
      • getBackgroundMusic -> EnvironmentAttributes#BACKGROUND_MUSIC
      • getBackgroundMusicVolume -> EnvironmentAttributes#MUSIC_VOLUME
      • $Builder
        • putAttributes - 从另一个映射放入所有属性。
        • setAttribute - 设置一个环境属性。
        • modifyAttribute - 修改生物群系的属性源。
    • BiomeSpecialEffects 现在是一个记录
      • getFogColor -> EnvironmentAttributes#FOG_COLOR
      • getWaterFogColor -> EnvironmentAttributes#WATER_FOG_COLOR
      • getSkyColor -> EnvironmentAttributes#SKY_COLOR
      • getAmbientParticleSettings -> EnvironmentAttributes#AMBIENT_PARTICLES
      • getAmbientLoopSoundEvent -> AmbientSounds#loop 环境属性
      • getAmbientMoodSettings -> AmbientSounds#mood 环境属性
      • getAmbientAdditionsSettings -> AmbientSounds#additions 环境属性
      • getBackgroundMusic -> EnvironmentAttributes#BACKGROUND_MUSIC
      • getBackgroundMusicVolume -> EnvironmentAttributes#MUSIC_VOLUME
  • net.minecraft.world.level.block
    • BedBlock#canSetSpawn -> BedRule#canSetSpawn 环境属性
    • CreakingHeartBlock#isNaturalNightEnvironmentAttributes#CREAKING_ACTIVE 取代
    • RespawnAnchorBlock#canSetSpawn 现在接受 ServerLevelBlockPos
  • net.minecraft.world.level.dimension
    • BuiltinDimensionTypes#*_EFFECTS 已移除
    • DimensionDefaults#OVERWORLD_CLOUD_HEIGHT 现在是一个 float
    • DimensionType
      • fixedTime -> hasFixedTime,现在是 boolean 而不是 OptionalLong
      • naturaleffectsLocation 已移除
      • skybox - 在维度内显示的天空盒。
      • cardinalLightType - 贯穿维度的光线类型。
      • timelines - 一组修改此维度环境属性的时间线。
      • ultraWarm -> EnvironmentAttributes#WATER_EVAPORATESFAST_LAVADEFAULT_DRIPSTONE_PARTICLE
      • bedWorks -> EnvironmentAttributes#BED_RULE
      • respawnAnchorWorks -> EnvironmentAttributes#RESPAWN_ANCHOR_WORKS
      • cloudHeight -> EnvironmentAttributes#CLOUD_HEIGHT
      • attribute - 获取此维度的属性。
      • piglinSafe$MonsterSettings#piglinSafe -> EnvironmentAttributes#PIGLINS_ZOMBIFY
      • hasRaids$MonsterSettings#hasRaids -> EnvironmentAttributes#CAN_START_RAID
      • timeOfDay 已移除
      • moonPhaseEnvironmentAttributes#MOON_PHASE 取代
      • hasEndFlashes - 返回天空盒是否是末地。
      • $CardinalLightType - 贯穿维度的光线。
      • $Skybox - 维度的天空盒。
  • net.minecraft.world.level.material.FogType#DIMENSION_OR_BOSS 已移除
  • net.minecraft.world.timeline
    • AttributeTrack - 一个轨道,应用属性修改器,其参数从给定的关键帧轨道采样。
    • AttributeTrackSampler - 一个烘焙的属性轨道。
    • Timeline - 一个属性到轨道的映射,基于时间(以刻为单位)模周期应用。
    • Timelines - 所有原版时间线。

游戏规则洗牌

游戏规则系统已在一定程度上被改造,允许将其键存储为适当的注册表对象,同时仍将其值限制为整数或布尔值。大多数类基本上只是其他类的组合。

现有游戏规则

现有的游戏规则仍然在 GameRules 类中,只是移到了不同的位置。它们的字段已被重命名,并似乎遵循一些基本规则:

  1. 规则不再有 RULE_ 前缀
  2. 规则现在使用下划线分隔单词
  3. DO 前缀已从规则名称中移除(例如,RULE_DOENTITYDROPS -> ENTITY_DROPS
  4. SPAWNING 后缀已替换为 SPAWN_ 前缀(例如,RULE_DOMOBSPAWNING -> SPAWN_MOBS
  5. DISABLE 前缀已移除,意味着它们的值被反转(例如,RULE_DISABLERAIDS -> RAIDS

虽然有一些边缘情况,但在之前的游戏规则名称中搜索特定单词很可能会引导您找到新名称(例如,在 RULE_ANNOUNCEADVANCEMENTS 中搜索 ADVANCEMENT 会找到 SHOW_ADVANCEMENT_MESSAGES)。

要实际从游戏规则中获取值,您将使用 GameRules#get 而不是之前的 getBooleangetInteger。类型从注册的 GameRule 上的泛型获得。

// 使用 ServerLevel level
boolean fallDamage = level.getGameRules().get(GameRules.FALL_DAMAGE);

此外,设置游戏规则现在简化为调用 GameRules#set——接受 GameRule、值和当前服务器,如果更改通过 MinecraftServer#onGameRuleChanged 传播,通常应该这样做。

// 使用 ServerLevel level
level.getGameRules().set(GameRules.FALL_DAMAGE, false, level.getServer());

创建游戏规则

游戏规则通过 GameRule 类创建,它基本上是一个类型定义,说明游戏规则如何根据其调用者运行。其泛型表示所持有的值的类型。唯一将此与通用类型区分开的硬编码概念是,实际参数可以被限制在特定范围内,并且它们存储默认值。否则,这些字段与其在 GameRules$TypeGameRules$Key 中的前身基本相同。

然后,一旦创建,GameRule 必须静态注册到 BuiltInRegistries#GAME_RULE

public static final GameRule<Integer> EXAMPLE_RULE = Registry.register(
    BuiltInRegistries.GAME_RULE
    Identifier.withNamespaceAndPath("examplemod", "example_rule"),
    new GameRule(
        // 最能代表游戏规则的类别。
        // 这仅在首次构造世界时
        // 由编辑游戏规则屏幕使用。
        // 可以通过调用 `GameRuleCategory#register` 或仅使用其构造函数
        // 创建自定义类别,因为排序顺序未使用
        GameRuleCategory.register(
            Identifier.withNamespaceAndPath("examplemod", "example_category")
        ),
        // 游戏规则的类型,表示泛型的
        // JSON 模式版本。
        // 这仅由管理系统用于
        // 检查非类型化规则。
        GameRuleType.INT,
        // 用于在命令中序列化值的参数类型。
        // 这可以根据构造函数进行范围限制。
        IntegerArgumentType.integer(0, 5),
        // 一个调用者,通常在访问过程中运行
        // 对于每个游戏规则。
        // 此调用者仅由编辑游戏规则屏幕使用
        // 用于添加修改值的正确组件。
        // 不应在此处使用 `GameRuleTypeVisitor#visit`
        // 因为访问者已经调用了该函数。
        GameRuleTypeVisitor::visitInteger,
        // 用于将游戏规则序列化到磁盘
        // 或用于管理服务的编解码器。
        // 这可以根据构造函数进行范围限制。
        Codec.intRange(0, 5),
        // 一个将设置值映射到整数结果的函数
        // 在通过命令设置或查询游戏规则时使用。
        // 这是唯一 `0` 的结果不意味着命令失败的情况。
        gameRuleValue -> gameRuleValue,
        // 此规则的默认值。
        3,
        // 此规则在游戏中启用所需的功能标志集。
        // 空的标志集意味着它应始终启用。
        FeatureFlagSet.of()
    )
);
  • net.minecraft.client.gui.screens.worldselection
    • EditGameRulesScreen
      • $BooleanRuleEntry 现在接受 GameRule<Boolean> 而不是 GameRules$BooleanValue
      • $EntryFactory 不再限制其泛型
      • $IntegerRuleEntry 现在接受 GameRule<Integer> 而不是 GameRules$IntegerValue
    • InitialWorldCreationOptions#disabledGameRules 现在是一个 GameRuleMap
  • net.minecraft.core.registries.BuiltInRegistries#GAME_RULERegistries#GAME_RULE - 游戏规则注册表。
  • net.minecraft.gametest.framework.TestEnvironmentDefinition
    • $SetGameRules 现在接受 GameRulesMap 而不是 $Entry
      • entry$Entry 已移除
  • net.minecraft.server.MinecraftServer#onGameRuleChanged 现在接受 GameRule 和值,而不是字符串键和 $Value 包装器
  • net.minecraft.server.jsonrpc.api.Schema
    • RULE_TYPE_SCHEMA 现在是 GameRuleType 而不是 GameRulesService$RuleType
    • TYPED_GAME_RULE_SCHEMA 现在是 GameRulesService$GameRuleUpdate 而不是 GameRulesService$TypedRule
    • UNTYPED_GAME_RULE_SCHEMA 现在是 GameRulesService$GameRuleUpdate 而不是 GameRulesService$UntypedRule
  • net.minecraft.server.jsonrpc.internalapi
    • GameRules 接口已移除
    • MinecraftGameRuleService#getRule -> getRuleValue
  • net.minecraft.server.jsonrpc.methods.GameRulesService
    • $RuleType 已移除
    • $TypedRule$UntypedRule -> $GameRuleUpdate,不是一对一
  • net.minecraft.server.notifications.NotificationService#onGameRuleChanged 现在接受 GameRule 和值,而不是字符串键和 $Value 包装器
  • net.minecraft.world.level.GameRules
    • 静态规则键现在位于 .gamerules.GameRules 中,没有 RULE_ 前缀,单词之间使用下划线
      • DO 已从名称中移除(例如,RULE_DOENTITYDROPS -> ENTITY_DROPS
      • SPAWNING 名称现在以 SPAWN_ 开头(例如,RULE_DOMOBSPAWNING -> SPAWN_MOBS
    • 将键映射到其关联值的映射行为现在由 GameRuleMap 处理
      • getBooleangetInteger -> get
    • $Key$Type -> GameRule,不是一对一
      • GameRule 实现 FeatureElement
    • $Category -> GameRuleCategory,不是一对一
    • $Value$BooleanValue$IntegerValue 已移除,被直接包装的对象取代
    • $GameRuleTypeVisitor -> GameRuleTypeVisitor

小幅迁移

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

使用注解

Mojang 最近为一些整数值和标志添加了注解,标记其预期用途。这不会以任何方式影响模组制作者,因为它似乎是一种对传递的值执行静态分析的方法,可能用于某种验证。

  • com.mojang.blaze3d.buffers.GpuBuffer$Usage - 一个注解,标记给定的整数是否定义了特定缓冲区的用法标志。
  • com.mojang.blaze3d.platform.InputConstants$Value - 一个注解,标记给定的整数是否定义了设备的输入。
  • com.mojang.blaze3d.buffers.GpuTexture$Usage - 一个注解,标记给定的整数是否定义了特定纹理的用法标志。
  • net.minecraft.client.input
    • InputWithModifiers$Modifiers - 一个注解,标记给定的整数是否定义了输入的修饰符。
    • KeyEvent$Action - 一个注解,标记给定的整数是否定义了输入正在执行的操作(即,按下、释放、重复)。
    • MouseButtonInfo
      • $Action - 一个注解,标记给定的整数是否定义了鼠标正在执行的操作(即,按下、释放、重复)。
      • $MouseButton - 一个注解,标记给定的整数是否定义了鼠标的输入。
  • net.minecraft.server.level.TicketType$Flags - 一个注解,标记给定的整数是否定义了加载票类型的标志。
  • net.minecraft.world.level.block.Block$UpdateFlags - 一个注解,标记给定的整数是否定义了方块更新的标志。

文本收集器

ActiveTextCollector 是一种提交字符串和组件进行渲染的方法,旨在提供对齐的通用实用程序,特别是对于超出屏幕的文本。虽然这不一定取代 GuiGraphics#drawString,但一些小部件需要使用 ActiveTextCollector,例如 AbstractStringWidget#renderLines

可以通过调用 GuiRenderer#textRenderer* 方法之一来创建 ActiveTextCollector。它们接受一个 $HoveredTextEffects,它处理如何渲染组件的悬停和点击事件,以及一个用于任何额外处理的 Style 消费者回调。它还存储一组默认参数,这些参数基本上代表当前的姿势不透明度和屏幕矩形。

有两种方法可以提交一段文本进行渲染:accept 用于标准字符串,以及 acceptScrolling* 用于超出矩形的屏幕,以大约每秒一个单位的速度在屏幕上来回滚动(请参阅辅助功能设置中的示例)。accept 最多接受五个参数:X 位置的对齐方式(TextAlignment#LEFT 像正常一样,CENTER 文本的中心,RIGHT 文本的末尾)、对齐的 X 位置、Y 位置、要覆盖的参数以及文本。acceptScrolling 最多接受七个参数:文本、居中对齐的起始 X 位置、最左边的 X 位置、最右边的 X 位置、最顶部的 Y 位置、最底部的 Y 位置以及要覆盖的参数。

// 在某个带有 GuiGraphics graphics 的方法中
ActiveTextCollector collector = graphics.textRenderer(
    // 渲染悬停和点击事件
    HoveredTextEffects.TOOLTIP_AND_CURSOR;
);

collector.accept(
    // 将文本对齐到中心
    TextAlignment.CENTER,
    // 起始 X(在这种情况下是中心位置)
    20,
    // 起始 Y
    0,
    // 要使用的参数
    collector.defaultParameters(),
    // 要显示的文本
    Component.literal("世界你好!")
);
  • net.minecraft.client.gui
    • ActiveTextCollector - 一个用于渲染具有某些参数和对齐方式的文本的辅助工具。
    • GuiGraphics 现在接受鼠标 XY
      • textRenderer* - 用于构造在适当位置提交文本的辅助工具的方法。
      • $HoveredTextEffects - 一个枚举,定义在使用文本收集器时应用的文本效果。
  • net.minecraft.client.gui.components
    • AbstractButton 现在扩展 AbstractWidget$WithInactiveMessage 而不是 AbstractWidget
      • renderWidget 现在是 final
        • 请改用 renderContents 来提交元素
        • 应在 renderContents 中调用 renderDefaultSprite 以 blit 默认精灵
      • renderString -> renderDefaultLabel,不是一对一
    • AbstractSliderButton 现在扩展 AbstractWidget$WithInactiveMessage 而不是 AbstractWidget
    • AbstractStringWidget
      • visitLines - 处理将文本元素提交到屏幕。
      • setColorgetColor 已移除
        • 请改用 visitLines 中的 ActiveTextCollector
      • setComponentClickHandler - 设置当点击具有提供样式的组件时的处理程序。
    • AbstractWidget
      • renderScrollingString -> renderScrollingStringOverContents,不是一对一
      • getAlpha - 获取小部件的 alpha 值。
      • $WithInactiveMessage - 一个小部件,可以在不活动时更改显示的消息。
    • Button 现在是抽象的
      • $Plain 复制了以前的行为
    • ChatComponent
      • MESSAGE_BOTTOM_TO_MESSAGE_TOP - 聊天组件的高度。
      • render 现在接受 Font 和一个 boolean,表示是否在插入时更改光标
      • captureClickableText - 捕获要提交的可点击文本。
      • handleChatQueueClickedQUEUE_EXPAND_ID 取代,不是一对一
      • getClickedComponentStyleAt -> $ChatGraphicsAccess#handleMessage,不是一对一
      • getMessageTagAt -> $ChatGraphicsAccess#handleTaghandleTagIcon;不是一对一
      • getWidthgetHeightgetScale 现在是私有的
      • $AlphaCalculator - 计算给定聊天行的 alpha 值。
      • $ChatGraphicsAccess - 一个用于处理聊天输入提交的接口。
      • $LineConsumer 不再接受前三个 int
    • FittingMultilineTextWidget#setColor 已移除
      • 请改用 visitLines 中的 ActiveTextCollector
    • MultiLineLabel
      • rendergetStyle -> visitLines,不是一对一
      • $Align -> TextAlignment
    • MultiLineTextWidget#setColorconfigureStyleHandling 已移除
      • 请改用 visitLines 中的 ActiveTextCollector
    • SplashRenderer 现在接受 Component 而不是 String
    • SpriteIconButton#renderSprite - 提交精灵图标。
    • StringWidget#setColor 已移除
      • 请改用 visitLines 中的 ActiveTextCollector
    • TabButton 现在扩展 AbstractWidget$WithInactiveMessage 而不是 AbstractWidget
      • renderString -> renderLabel,现在是私有的,不是一对一
  • net.minecraft.client.gui.screens.inventory.BookViewScreen#getClickedComponentStyleAt -> visitText,现在是私有的,不是一对一

共享文本区域调试器

添加了一个新的调试器,用于绘制每个字形的边界框,包括空字形。颜色在每个字形之间略有偏移以便于区分,并且根据是否存在点击或悬停事件的某种组合而完全改变。

  • net.minecraft.SharedConstants#DEBUG_ACTIVE_TEXT_AREAS - 用于调试器绘制每个字形的边界和效果的标志。
  • net.minecraft.client.gui.Font
    • prepareText 现在有一个重载,表示是否在空区域渲染某些内容
    • $GlyphVisitor
      • acceptGlyph 现在接受 TextRenderable$Styled 而不是 TextRenderable
      • acceptEmptyArea - 接受一个空区域以绘制到屏幕。
    • $PreparedTextBuilder 现在接受是否包括空区域以进行渲染
  • net.minecraft.client.gui.font
    • ActiveArea - 定义要绘制区域的边界和样式。
    • EmptyArea - 一个内部没有任何内容的区域。
    • PlainTextRenderable 现在实现 TextRenderable$Styled 而不是 TextRenderable
      • widthheightascent - 对象的边界。
    • TextRenderable$Styled - 一个为其边界定义某个活动区域的文本可渲染对象。
  • net.minecraft.client.gui.font.glyphs.BakedGlyph#createGlyph 现在返回 TextRenderable$Styled

JSpecify 注解

Mojang 已从使用他们自己的注解混合,转向在需要时使用 JSpecify 提供的注解。因此,不再默认所有字段、方法和参数都被标记为非空,而是由 NullMarked 取代,它认为类型用法是非空的,除非显式注解为 Nullable,除了一些特殊情况。

  • com.mojang.blaze3d.FieldsAreNonnullByDefaultMethodsReturnNonnullByDefault 已移除
  • com.mojang.math.FieldsAreNonnullByDefaultMethodsReturnNonnullByDefault 已移除
  • net.minecraft.FieldsAreNonnullByDefaultMethodsReturnNonnullByDefault 已移除

槽位来源

槽位来源是对之前在潜影盒中的内容掉落系统的扩展,允许任何战利品表从某些容器槽位中提取其条目。这可以在任何启用 LootContext 的位置使用,尽管目前它仅作为战利品池条目实现。

在原版中,槽位来源的工作方式是让某个 LootContextArg(指向某个战利品上下文参数值)返回一个实现 SlotProvider 的对象。目前,这指的是任何 ContainerEntity 实现。然后,SlotProviderSlotSource#provide 用于构造一个 SlotCollection:一个深拷贝 ItemStack 的流。存储在集合中的堆栈然后被传递到池的输出。由于这一切都在某个 SlotSource#provide 实现中完成,它可以引用任何东西(不仅仅是 SlotProvider),只要它可以将该数据转换为 SlotCollection

// 一个槽位来源,其“槽位”是物品标签中的元素。
public record TagSlotSource(TagKey<Item> tag) implements SlotSource {

    public static final MapCodec<TagSlotSource> MAP_CODEC = TagKey.codec(Registries.ITEM)
        .fieldOf("tag").xmap(TagSlotSource::new, TagSlotSource::tag);
    
    @Override
    public SlotCollection provide(LootContext ctx) {
        // 获取标签的持有者集
        Optional<HolderSet.Named<Item>> holderSetOpt = ctx.getResolver()
            .lookup(Registries.ITEM).flatMap(getter -> getter.get(this.tag));
        
        // 流式传输元素并映射到 SlotCollection
        return holderSetOpt.map(holderSet ->
            // `Item#getDefaultInstance` 返回一个新副本,因此可以使用。
            // 如果 ItemStack 已经存在,则应对每个调用 `ItemStack#copy`。
            (SlotCollection) () -> holderSet.stream().map(holder -> holder.value().getDefaultInstance())
        ).orElse(SlotCollection.EMPTY);
    }

    @Override
    public MapCodec<? extends SlotSource> codec() {
        // 用于序列化槽位来源的编解码器
        return MAP_CODEC;
    }
}

// 映射编解码器需要注册到槽位来源类型注册表
Registry.register(
    BuiltInRegistries.SLOT_SOURCE_TYPE
    Identifier.withNamespaceAndPath("examplemod", "tag"),
    TagSlotSource.MAP_CODEC
);
// 一个示例战利品表
{
    // ...
    "pools": [
        {
            "rolls": 1.0,
            "bonus_rolls": 0.0,
            "entries": [
                {
                    // 使用槽位来源战利品池
                    "type": "minecraft:slots",
                    "slot_source": {
                        // 我们的槽位来源
                        "type": "examplemod:tag",
                        "tag": "minecraft:planks"
                    }
                }
            ]
        }
        // ...
    ]
}
  • net.minecraft.advancements.criterion.SlotsPredicate#matches 现在接受 SlotProvider 而不是 Entity
  • net.minecraft.core.registries.BuiltInRegistries#SLOT_SOURCE_TYPERegistries#SLOT_SOURCE_TYPE - 槽位来源类型注册表。
  • net.minecraft.world.Container 现在扩展 SlotProvider
    • getSlot - 获取单个物品的访问。
  • net.minecraft.world.entity
    • Entity 现在实现 SlotProvider
    • SlotAccess
      • NULL 已移除
      • forContainer -> forListElement,不是一对一
    • SlotProvider - 一个通过槽位提供对其内部存储的某些访问的对象。
  • net.minecraft.world.item.slot
    • CompositeSlotSource - 多个槽位来源的组合。
    • ContentsSlotSource - 获取槽位内容。
    • EmptySlotSource - 一个空的槽位来源。
    • FilteredSlotSource - 根据物品谓词过滤提供的槽位来源。
    • GroupSlotSource - 将多个槽位来源组合成一个连接的集合。
    • LimitSlotSource - 将提供的槽位来源限制为最大大小。
    • RangeSlotSource - 获取所需的槽位范围。
    • SlotCollection - 一个槽位的集合,用于获取物品副本。
    • SlotSource - 给定战利品上下文,返回一个要提供的槽位集合。
    • SlotSources - 原版提供的槽位来源。
    • TransformedSlotSource - 转换提供的槽位来源。
  • net.minecraft.world.level.storage.loot.ContainerComponentManipulator#getSlots - 获取堆栈上数据组件的槽位。
  • net.minecraft.world.level.storage.loot.entries
    • LootPoolEntries#SLOTS - 一个使用来自源的槽位的池。
    • SlotLoot - 一个从某个槽位来源获取其物品的池。

僵尸鹦鹉螺变体

僵尸鹦鹉螺是变体数据包注册表对象的最新添加,接受熟悉的模型和纹理覆盖以及生成条件:

// 文件位于:
// - `data/examplemod/zombie_nautilus_variant/example_zombie_nautilus.json`
{
    // 指向 `assets/examplemod/textures/entity/nautilus/example_zombie_nautilus.png` 的纹理
    "asset_id": "examplemod:entity/nautilus/example_zombie_nautilus",
    // 定义用于选择渲染僵尸鹦鹉螺变体的实体模型的 `ZombieNautilusVariant$ModelType`
    "model": "warm",
    "spawn_conditions": [
        // 此变体生成的条件
        {
            "priority": 0
        }
    ]
}
  • net.minecraft.core.component.DataComponents#ZOMBIE_NAUTILUS_VARIANT - 僵尸鹦鹉螺的变体。
  • net.minecraft.core.registries.Registries#ZOMBIE_NAUTILUS_VARIANT - 僵尸鹦鹉螺变体的注册表键。
  • net.minecraft.network.syncher.EntityDataSerializers#ZOMBIE_NAUTILUS_VARIANT - 僵尸鹦鹉螺的变体。
  • net.minecraft.world.entity.animal.nautilus
    • ZombieNautilusVariant - 僵尸鹦鹉螺的变体。
    • ZombieNautilusVariants - 所有原版僵尸鹦鹉螺变体。

OptionEnum 移除

OptionEnum 已被移除,转而使用带有期望值和编解码器的 OptionInstance$Enum 构造函数。因此,大多数 byId 方法已被一些编解码器取代,并且可翻译条目现在存储为 Component 而不是翻译键字符串。

  • net.minecraft.client
    • AttackIndicatorStatus 不再实现 OptionEnum
      • byId -> LEGACY_CODEC,不是一对一
      • getKey -> caption,不是一对一
    • CloudStatus 不再实现 OptionEnum
      • getKey -> caption,不是一对一
    • InactivityFpsLimit 不再实现 OptionEnum
      • getKey -> caption,不是一对一
    • OptionInstance#forOptionEnum 已移除
    • PrioritizeChunkUpdate 不再实现 OptionEnum
      • getKey -> caption,不是一对一
      • byId -> LEGACY_CODEC,不是一对一
  • net.minecraft.client.sounds.MusicManager$MusicFrequency 不再实现 OptionEnum
    • getKey -> caption,不是一对一
  • net.minecraft.server.level.ParticleStatus 不再实现 OptionEnum
    • getKey -> caption,不是一对一
    • byId -> LEGACY_CODEC,不是一对一
  • net.minecraft.util.OptionEnum 已移除
  • net.minecraft.world.entity.HumanoidArm 不再实现 OptionEnum
    • BY_ID 现在是私有的
    • getKey -> caption,不是一对一
  • net.minecraft.world.entity.player.ChatVisbility 不再实现 OptionEnum
    • byId -> LEGACY_CODEC,不是一对一
    • getKey -> caption,不是一对一

特定逻辑变更

  • net.minecraft.client.renderer.entity.EntityRenderState#lightCoords 现在默认为 0xF000F0。
  • net.minecraft.client.gui.screens.inventory.AbstractContainerScreen#keyPressed 如果键未被屏幕处理,不再返回 true,而是返回 false
  • net.minecraft.util.Mth#clampedLerp 两个重载的参数顺序已重新排列。这些方法现在接受步长、原始值和下一个值;而不是原始值、下一个值和步长值。

标签变更

  • minecraft:biome
    • plays_underwater_music 已移除
      • BackgroundMusic#underwaterMusic 环境属性取代
    • has_closer_water_fog 已移除
      • EnvironmentAttributes#WATER_FOG_END_DISTANCE 取代
    • increased_fire_burnout 已移除
      • EnvironmentAttributes#INCREASED_FIRE_BURNOUT 取代
    • snow_golem_melts 已移除
      • EnvironmentAttributes#SNOW_GOLEM_MELTS 取代
    • without_patrol_spawns 已移除
      • EnvironmentAttributes#CAN_PILLAGER_PATROL_SPAWN 取代
    • spawns_coral_variant_zombie_nautilus
  • minecraft:block
    • can_glide_through
  • minecraft:entity_type
    • burn_in_daylight
    • can_float_while_ridden
    • can_wear_nautilus_armor
    • nautilus_hostiles
  • minecraft:item
    • camel_husk_food
    • zombie_horse_food
    • nautilus_bucket_food
    • nautilus_food
    • nautilus_taming_items
    • spears
    • enchantable/lunge
    • enchantable/sword -> enchantable/melee_weaponenchantable/sweeping
  • minecraft:timeline
    • universal
    • in_overworld
    • in_nether
    • in_end

新增列表

  • com.mojang.blaze3d.GraphicsWorkarounds#isAmd - GPU 供应商是否为 AMD。
  • com.mojang.blaze3d.opengl
    • GlConst#GL_POINTS - 定义点图元作为要渲染的类型。
    • GlTimerQuery - 查询对象(通常是经过的时间)的 OpenGL 实现。
  • com.mojang.blaze3d.platform.InputConstants#MOUSE_BUTTON_* - 鼠标点击的输入,用数字表示,因为它们可能有不同的预期用途。
  • com.mojang.blaze3d.systems
    • CommandEncoder#timerQueryBegintimerQueryEnd - 用于跟踪经过时间的处理程序。
    • GpuQuery - 对任意对象的查询,例如经过的时间。
  • com.mojang.blaze3d.vertex
    • DefaultVertexFormat
      • POSITION_COLOR_LINE_WIDTH - 一个指定位置、颜色和线宽的顶点格式。
      • POSITION_COLOR_NORMAL_LINE_WIDTH - 一个指定位置、颜色、法线和线宽的顶点格式。
    • VertexFormat$Mode#POINTS - 一个绘制点的顶点模式。
    • VertexFormatElement#LINE_WIDTH - 一个接受一个表示宽度的浮点数的顶点元素。
  • com.mojang.math
    • OctahedralGroup
      • BLOCK_ROT_* - 表示方块旋转的常量。
      • permutation - 返回对称群。
    • Quadrant#fromXYZAngles - 获取表示三个象限旋转的八面体群。
    • SymmetricGroup3#inverse - 返回逆群。
  • net.minecraft
    • SharedConstants
      • MAX_CLOUD_DISTANCE - 玩家可以渲染的最大云范围。
      • DEFAULT_RANDOM_TICK_SPEED - 默认随机刻速度。
    • Util#localizedDateFormatter - 返回给定样式的本地化 DateTimeFormatter
  • net.minecraft.advancements.criterion
    • DataComponentMatchers$Builder#any - 匹配组件的某些数据是否存在。
    • SpearMobsTrigger - 一个触发器,检查玩家使用动能武器刺穿的实体数量。
  • net.minecraft.client
    • GuiMessage
      • splitLines - 将组件以所需宽度拆分为行。
      • getTagIconLeft - 获取内容的宽度,外加四个像素的填充。
    • KeyMapping$Category#DEBUG - 调试键盘类别。
    • MusicToastDisplayState - 一个枚举,表示音乐吐司应如何显示。
    • NarratorStatus#LEGACY_CODEC - 用于反序列化枚举旁白状态的编解码器。
    • OptionInstance
      • $IntRangeBase
        • next - 获取下一个值。
        • previous - 获取上一个值。
      • $SliderableEnum - 一个在枚举选项之间选择的滑块。
      • $SliderableValueSet
        • next - 获取下一个值。
        • previous - 获取上一个值。
    • Options
      • keyToggleGui - 一个切换游戏内 GUI 的按键映射。
      • keyToggleSpectatorShaderEffects - 一个切换与相机实体绑定的着色器效果的按键映射。
      • keyDebug*debugKeys - 调试渲染器的按键映射。
      • weatherRadius - 区域中天气粒子渲染的半径。
      • cutoutLeaves - 树叶是否应以切割或实体模式渲染。
      • vignette - 是否应在屏幕上应用晕影。
      • improvedTransparency - 是否使用透明度后处理器。
      • chunkSectionFadeInTime - 区块首次渲染时淡入应花费的秒数。
      • maxAnisotropyBit - 各向异性过滤级别的位值。
      • maxAnisotropyValue - 各向异性过滤级别。
  • net.minecraft.client.animation.definitions.NautilusAnimation - 鹦鹉螺的动画定义。
  • net.minecraft.client.data.models.ItemModelGenerators
    • generateSpear - 生成矛物品模型。
    • generateItemWithTintedBaseLayer - 生成一个基础层被染色的双层物品模型。
  • net.minecraft.client.data.models.model.ModelTemplates#SPEAR_IN_HAND - 手持矛模型的模板。
  • net.minecraft.client.gui.components
    • AbstractButton#setOverrideRenderHighlightedSprite - 覆盖是否使用聚焦启用/禁用精灵。
    • Checkbox#adjustWidth - 使用消息、字体及其初始 X 位置设置小部件的宽度。
    • CycleButton
      • $Builder#withSprite - 设置根据当前按钮状态获取精灵的供应商。
      • $DisplayState - 按钮应如何显示。
      • $SpriteSupplier - 根据当前按钮状态获取精灵位置。
    • EditBox#setInvertHighlightedTextColor - 设置是否反转高亮文本颜色。
    • FocusableTextWidget
      • getPadding - 返回文本填充。
      • updateWidth - 更新文本可以占用的宽度。
      • updateHeight - 更新文本可以占用的高度。
      • $Builder - 构建组件。
    • MultiLineTextWidget#getTextXgetTextY - 获取文本位置。
    • OptionsList
      • addHeader - 添加一个标题条目。
      • resetOption - 重置选项值。
      • $AbstractEntry - 定义选择列表中的元素。
      • $HeaderEntry - 一个表示部分标题的条目。
      • $OptionInstanceWidget - 一个包含小部件和可选的选项实例的记录。
    • ResettableOptionWidget - 一个可以将其值重置为默认值的小部件。
    • SelectableEntry - 一个用于检查鼠标是否在特定区域的实用程序。
  • net.minecraft.client.gui.layouts.HeaderAndFooterLayout#MAGIC_PADDING - 元素之间的常见填充。
  • net.minecraft.client.gui.screens.advancements
    • AdvancementTab#canScrollHorizontallycanScrollVertically - 检查标签页数据是否可以在给定方向上滚动。
    • AdvancementTabType#getWidthgetHeight - 获取标签页的宽度/高度。
  • net.minecraft.client.gui.screens.debug.DebugOptionsScreen#getOptionList - 返回调试屏幕的选项列表。
  • net.minecraft.client.gui.screens.inventory
    • AbstractMountInventoryScreen - 一个表示坐骑库存的屏幕。
    • EffectsInInventory
      • SPACING - 效果之间的间距。
      • SPRITE_SQUARE_SIZE - 效果图标的大小。
    • NautilusInventoryScreen - 鹦鹉螺库存的屏幕。
  • net.minecraft.client.gui.screens.options
    • OptionsSubScreen#resetOption - 将选项值重置为默认值。
    • VideoSettingsScreen#updateTransparencyButton - 将透明度按钮设置为当前选项值。
  • net.minecraft.client.gui.screens.packs.TransferableSelectionList$PackEntry#ICON_SIZE - 资源包图标的大小。
  • net.minecraft.client.gui.screens.recipebook.RecipeBookTabButton#selectunselect - 处理标签页显示选择。
  • net.minecraft.client.input.InputQuirks#EDIT_SHORTCUT_KEY_LEFTEDIT_SHORTCUT_KEY_RIGHT -> InputWithModifiers#hasControlDownWithQuirk,不是一对一
  • net.minecraft.client.model.HumanoidModel$ArmPose
    • SPEAR - 矛的第三人称手臂姿势。
    • animateUseItem - 给定实体状态、使用时间、手臂和堆栈,修改 PoseStack
    • affectsOffhandPose - 手臂动画是否会影响副手姿势。
  • net.minecraft.client.model.animal.nautilus
    • NautilusArmorModel - 鹦鹉螺的盔甲模型。
    • NautilusModel - 鹦鹉螺的模型。
    • NautilusSaddleModel - 鹦鹉螺的马鞍模型。
  • net.minecraft.client.model.effects.SpearAnimations - 使用矛时执行的动画。
  • net.minecraft.client.model.geom
    • ModelLayers
      • *NAUTILUS* - 鹦鹉螺的模型层。
      • UNDEAD_HORSE*_ARMOR - 亡灵马的盔甲模型层。
    • PartName
      • INNER_MOUTHLOWER_MOUTH - 嘴的部件名称。
      • SHELL - 壳的部件名称。
      • *_CORAL* - 僵尸鹦鹉螺上珊瑚的部件名称。
  • net.minecraft.client.model.geom.builders.UVPair#packunpack* - 处理将 UV 打包/解包为 long
  • net.minecraft.client.model.monster.nautilus.ZombieNautilusCoralModel - 僵尸鹦鹉螺温暖变体的模型。
  • net.minecraft.client.model.monster.skeleton.SkeletonModel#createSingleModelDualBodyLayer - 创建一个焦尸层定义。
  • net.minecraft.client.multiplayer
    • ClientPacketListener#hasClientLoaded - 客户端是否已加载。
    • MultiPlayerGameMode#piercingAttack - 发起冲刺攻击。
  • net.minecraft.client.player.LocalPlayer#raycastHitResult - 获取给定部分刻下相机实体的命中结果。
  • net.minecraft.client.renderer
    • DynamicUniforms
      • CHUNK_SECTION_UBO_SIZE - 区块部分的统一缓冲区对象大小。
      • writeChunkSections - 将可变参数的区块部分写入统一存储。
      • $ChunkSectionInfo - 区块部分的动态统一变量。
    • GameRenderer
      • updateCamera - 调用相机的设置函数。
      • getPanoramicScreenshotParameters - 获取全景模式的截图参数。
    • PanoramicScreenshotParameters - 全景模式的截图参数。
    • Sheets#CELESTIAL_SHEET - 天体纹理的图集。
  • net.minecraft.client.renderer.blockentity.BlockEntityWithBoundingBoxRenderer#STRUCTURE_VOIDS_COLOR - 结构的虚空颜色。
  • net.minecraft.client.renderer.chunk.SectionRenderDispatcher$RenderSection
    • getVisibility - 返回区块当前的 alpha 值。
    • setFadeDuration - 设置区块淡入所需的时间。
    • setWasPreviouslyEmptywasPreviouslyEmpty - 处理该部分之前是否不存在。
  • net.minecraft.client.renderer.entity
    • CamelHuskRenderer - 骆驼干尸的实体渲染器。
    • CamelRenderer#createCamelSaddleLayer - 创建骆驼的马鞍层。
    • NautilusRenderer - 鹦鹉螺的实体渲染器。
    • ParchedRenderer - 焦尸的实体渲染器。
    • ZombieNautilusRenderer - 僵尸鹦鹉螺的实体渲染器。
  • net.minecraft.client.renderer.entity.state
    • ArmedEntityRenderState
      • swingAnimationType - 挥动手臂时播放的动画。
      • ticksUsingItem - 物品已被使用的刻数。
      • getUseItemStackForArm - 根据手臂返回持有的物品堆栈。
    • LivingEntityRenderState#ticksSinceKineticHitFeedback - 自此实体被动能武器击中以来经过的刻数。
    • NautilusRenderState - 鹦鹉螺的实体渲染状态。
    • UndeadRenderState - 亡灵人形生物的实体渲染状态。
  • net.minecraft.client.renderer.item.ItemModelResolver#swapAnimationScale - 获取堆栈交换动画的缩放。
  • net.minecraft.client.renderer.state.LevelRenderState#gameTime - 当前游戏时间。
  • net.minecraft.client.resources.SplashManager 组件字段 - 特殊消息的组件。
  • net.minecraft.client.resources.model
    • BlockModelRotation#IDENTITY - 恒等旋转。
    • EquipmentClientInfo#NAUTILUS_* - 鹦鹉螺的层。
  • net.minecraft.core.Vec3i
    • multiply - 将每个分量乘以提供的标量。
    • toMutable - 返回一个可变的 Vector3i
  • net.minecraft.data.AtlasIds#CELESTIAL_SHEET - 天体纹理的图集。
  • net.minecraft.data.recipes.RecipeProvider#waxedChiseled - 打蜡的雕纹方块的配方。
  • net.minecraft.gametest.framework.GameTestHelper#getAbsoluteDirection - 从测试相对方向返回绝对方向。
  • net.minecraft.nbt.NbtAccounter
    • defaultQuota - 一个最大分配 2 MiB 的计数器。
    • uncompressedQuota - 一个最大分配 100 MiB 的计数器。
  • net.minecraft.network.chat.MutableComponent#withoutShadowStyle#withoutShadow - 从文本中移除阴影。
  • net.minecraft.network.protocol.game.ServerboundPlayerActionPacket$Action#STAB - 玩家执行了刺击动作。
  • net.minecraft.network.syncher.EntityDataSerializers#HUMANOID_ARM - 人形生物的主手。
  • net.minecraft.resources.Identifier#toShortString - 返回位置的字符串。如果命名空间是 minecraft,则省略。
  • net.minecraft.server
    • MinecraftServer
      • getServerActivityMonitor - 返回发送服务器活动通知的监视器。
      • getStopwatches - 返回 id 到计时器的映射。
    • ServerScoreboard#storeToSaveDataIfDirty - 如果脏则写入数据。
  • net.minecraft.server.commands.StopwatchCommand - 一个启动或停止秒表的命令。
  • net.minecraft.server.dedicated.DedicatedServerProperties#managementServerAllowedOrigins - 管理服务器的请求可以来自的来源。
  • net.minecraft.server.jsonrpc.OutgoingRpcMethods#SERVER_ACTIVITY_OCCURRED - Minecraft 服务器发出的关于服务器活动发生的请求。
  • net.minecraft.server.jsonrpc.api.Schema
    • BOOL_OR_INT_SCHEMA - 一个可以是布尔值或整数的字段的模式。
    • typedCodec - 返回模式的编解码器。
    • info - 返回模式的副本。
  • net.minecraft.server.level
    • ChunkMap#getChunkDataFixContextTag - 返回区块数据的数据修复标签。
    • ServerLevel
      • getDayCount - 获取经过的天数。
      • canSpreadFireAround - 火是否可以在给定的方块位置周围蔓延。
  • net.minecraft.server.network
    • EventLoopGroupHolder - 一个用于管理与某个端点(无论是本地还是基于套接字)通信的事件循环和通道的持有者。
    • ServerGamePacketListenerImpl#resetFlyingTicks - 重置玩家已飞行的刻数。
  • net.minecraft.server.notifications
    • NotificationService#serverActivityOccurred - 通知管理服务器活动已发生。
    • ServerActivityMonitor - 发送服务器活动通知的监视器。
  • net.minecraft.util
    • ARGB
      • srgbToLinearChannel - 将 sRGB 值转换为线性颜色空间。
      • linearToSrgbChannel - 将线性值转换为 sRGB 颜色空间。
      • meanLinear - 使用线性颜色空间计算四个值的平均值,然后将其转换回 sRGB。
      • addRgb - 添加 RGB 通道,使用第一个值的 alpha。
      • subtractRgb - 减去 RGB 通道,使用第一个值的 alpha。
      • multiplyAlpha - 将 alpha 值乘入提供的 ARGB 值。
      • linearLerp - 通过转换为线性颜色空间来线性插值颜色。
      • whiteblack - 具有提供 alpha 的颜色。
      • alphaBlend - 混合两种颜色及其 alpha 值。
      • vector4fFromARGB32 - 将 ARGB 值转换为四个浮点数。
    • Ease - 一个充满缓动函数的实用工具。
    • ExtraCodecs
      • NON_NEGATIVE_LONGPOSITIVE_LONG - 具有列出约束的长整数。
      • longRange - 一个验证其是否在提供范围内的长整数编解码器。
      • STRING_RGB_COLORSTRING_ARGB_COLOR - 一个允许以十六进制字符串形式表示 (A)RGB 值的编解码器。
      • MAX_PROPERTY_NAME_LENGTHMAX_PROPERTY_VALUE_LENGTHMAX_PROPERTY_SIGNATURE_LENGTHMAX_PROPERTIES - 与序列化属性映射相关的常量。
    • Mth
      • cube - 对数字进行立方。
      • chessboardDistance - 计算两对坐标之间的绝对最大差值;返回较大的轴差。
    • SpecialDates - 一个包含 Mojang 更改某些行为或渲染的日期的实用工具。
    • TriState
      • CODEC - 三态布尔值的编解码器。
      • from - 将布尔值转换为三态布尔值。
  • net.minecraft.util.profiling.jfr.JvmProfiler#onClientTick - 在客户端Tick上运行,接受当前的 FPS。
  • net.minecraft.util.profiling.jfr.event.ClientFpsEvent - 一个跟踪客户端 FPS 的事件。
  • net.minecraft.util.profiling.jfr.stats.FpsStat - 一个包含客户端 FPS 的记录。
  • net.minecraft.world
    • LockCode#canUnlock - 给定的玩家是否可以解锁此代码。
    • Stopwatch - 一个包含创建时间和已用时间的记录。
    • Stopwatches - 一个用于启动、管理和停止秒表的跟踪器。
  • net.minecraft.world.effect
    • MobEffects#BREATH_OF_THE_NAUTILUS - 防止用户在水下失去空气。
    • MobEffectUtil#shouldEffectsRefillAirsupply - 实体是否具有在液体中补充空气供应的效果。
  • net.minecraft.world.entity
    • Entity
      • getHeadLookAngle - 计算头部旋转的视图向量。
      • updateDataBeforeSync - 在同步到客户端之前更新实体中存储的数据。
      • computeSpeed - 计算实体的最后已知速度和位置。
      • getKnownSpeed - 获取实体的最后已知速度。
      • hasMovedHorizontallyRecently - 如果最后已知速度的水平距离大于 0,更具体地说是误差范围。
    • EntityProcessor - 加载实体时的后处理器。
    • EntityEvent#KINETIC_HIT - 当实体被动能武器击中时触发的事件。
    • HumanoidArm#STREAM_CODEC - 手臂枚举的网络编解码器。
    • LivingEntity
      • DEFAULT_KNOCKBACK - 击中时应用于实体的默认击退。
      • itemSwapTicker - 交换物品时花费的时间。
      • recentKineticEnemies - 最近使用动能武器攻击的攻击者。
      • lungeForwardMaybe - 应用冲刺效果。
      • causeExtraKnockback - 对击退应用乘法力。
      • wasRecentlyStabbedrememberStabbedEntity - 处理被动能武器刺中的敌人。
      • stabAttack - 处理生物被此实体刺中时的情况。
      • onAttack - 处理此实体攻击另一个实体时的情况。
      • getTicksUsingItem - 返回此物品已被使用的刻数。
      • getTicksSinceLastKineticHitFeedback - 自上次被动能武器击中此实体以来经过的刻数。
      • shouldTravelInFluid - 此实体是否应在给定的流体中移动。
      • travelInWater - 移动实体,就像它们在水中一样。
    • Mob#sunProtectionSlot - 保护实体免受阳光照射的装备槽位。
    • NeutralMob#level - 返回实体所在的等级。
    • PlayerRideableJumping#getPlayerJumpPendingScale - 返回玩家跳跃时应应用于实体的标量。
  • net.minecraft.world.entity.ai.attributes.Attributes#DEFAULT_ATTACK_SPEED - 默认攻击速度。
  • net.minecraft.world.entity.ai.memory.MemoryModuleType
    • CHARGE_COOLDOWN_TICKS - 冲刺攻击后的冷却刻数。
    • ATTACK_TARGET_COOLDOWN - 攻击目标前的冷却刻数。
  • net.minecraft.world.entity.ai.sensing.TemptingSensor#forAnimal - 一个传感器,特别处理动物实体,检查所需物品是否是食物。
  • net.minecraft.world.entity.animal.camel
    • Camel
      • getDashingSoundgetDashReadySound - 骆驼冲刺声音。
      • getStandUpSoundgetSitDownSound - 骆驼站/坐声音。
      • getSaddleSound - 骆驼马鞍声音。
    • CamelHusk - 骆驼干尸实体。
  • net.minecraft.world.entity.animal.equine.AbstractHorse#isMobControlled - 生物是否可以控制这匹马。
  • net.minecraft.world.entity.animal.nautilus
    • AbstractNautilus - 鹦鹉螺实体的核心。
    • Nautilus - 鹦鹉螺实体。
    • NautilusAi - 鹦鹉螺的大脑。
    • ZombieNautilus - 僵尸鹦鹉螺实体。
    • ZombieNautilusAi - 僵尸鹦鹉螺的大脑。
  • net.minecraft.world.entity.decoration.HangingEntity#hasLevelCollision - 此实体是否在给定边界内与方块或边界碰撞。
  • net.minecraft.world.entity.monster.skeleton.Parched - 焦尸实体。
  • net.minecraft.world.entity.monster.zombie.Husk$HuskGroupData - 尸壳的群组数据。
  • net.minecraft.world.entity.player.Player
    • cannotAttackWithItem - 检查玩家是否无法使用该物品攻击。
    • getItemSwapScale - 返回用于物品交换动画的标量。
    • resetOnlyAttackStrengthTicker - 重置攻击强度Tick器。
    • openNautilusInventory - 打开交互的鹦鹉螺的库存。
    • applyPostImpulseGraceTimeisInPostImpulseGraceTime - 处理脉冲之间的宽限期。
  • net.minecraft.world.food.FoodData#hasEnoughFood - 当前食物水平是否大于 6 饥饿值(或三个完整的饥饿条)。
  • net.minecraft.world.inventory
    • AbstractMountInventoryMenu - 坐骑的库存菜单。
    • NautilusInventoryMenu - 鹦鹉螺的库存菜单。
  • net.minecraft.world.item
    • HoneycombItem#WAXED_RECIPES - 打蜡方块到其配方类别和名称的映射。
    • Item$Properties
      • spear - 添加矛组件。
      • nautilusArmor - 添加鹦鹉螺盔甲组件。
    • ItemStack#matchesIgnoringComponents - 堆栈是否匹配,忽略所有匹配谓词的组件。
    • ItemUseAnimation
      • TRIDENT - 三叉戟使用动画。
      • hasCustomArmTransform - 动画是否提供自定义的手臂变换。
  • net.minecraft.world.item.enchantment
    • Enchantment#doLunge - 应用穿刺后攻击效果。
    • EnchantmentEffectComponents#POST_PIERCING_ATTACK - 穿刺攻击后应用的效果。
    • EnchantmentHelper#doLungeEffects - 在冲刺时应用效果。
    • LevelBasedValue$Exponent - 应用给定基数和指数的指数。
  • net.minecraft.world.item.enchantment.effects
    • ApplyEntityImpulse - 一个实体效果,在视角方向添加一个冲量。
    • ApplyExhaustion - 一个实体效果,如果玩家正在使用附魔物品,则应用食物消耗。
    • ScaleExponentially - 一个值效果,将值乘以某个数的指数次幂。
  • net.minecraft.world.level
    • Chunk#isValid - 区块位置是否在允许的最大世界坐标内(在 3000 万方块半径内)。
    • CollisionGetter
      • noEntityCollision - 实体在给定边界内是否不与另一个实体碰撞。
      • noBorderCollision - 实体在给定边界内是否不与世界边界碰撞。
    • Level#isInValidBounds - 方块位置是否不在允许的最大世界坐标外(Y 轴为建筑高度,XZ 轴为 3000 万方块半径)。
    • MoonPhase - 一个表示月相的枚举。
  • net.minecraft.world.level.border.WorldBorder$MovingBorderExtent#getPreviousSize - 获取边界的先前大小。
  • net.minecraft.world.level.chunk.storage
    • IOWorker#STORE_EMPTY - 一个提供的 null 标签。
    • LegacyTagFixer - 一个处理如何升级标签的接口,例如对于区块。
    • SimpleRegionStorage
      • isOldChunkAround - 来自先前版本的区块是否仍然存在于此版本中。
      • injectDatafixingContext - 当上下文不为 null 时,将其添加到给定的标签。
      • markChunkDone - 将区块标记为已完成升级到当前版本。
      • chunkScanner - 获取用于扫描区块的访问。
  • net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler#LAST_MONOLYTH_STRUCTURE_DATA_VERSION - 返回包含故障巨石的最后数据版本。
  • net.minecraft.world.level.storage.loot.LootContextArg - 用于查询的战利品上下文参数。
  • net.minecraft.world.level.storage.loot.functions.DiscardItem - 一个丢弃战利品、返回空堆栈的战利品函数。
  • net.minecraft.world.phys.Vec3
    • offsetRandomXZ - 在 XZ 方向上按随机量偏移点。
    • rotation - 计算向量的旋转。
    • applyLocalCoordinatesToRotation - 将相对于向量当前旋转的分量相加。
    • isFinite - 返回向量的所有分量是否为有限值(不是 NaN 或无穷大)。
  • net.minecraft.world.scores
    • Scoreboard
      • packPlayerTeams - 将玩家队伍打包成可序列化的格式。
      • packObjectives - 将目标打包成可序列化的格式。
      • packDisplaySlots - 将显示槽位打包成可序列化的格式。
    • ScoreboardSaveData
      • getDatasetData - 处理打包的记分板。
      • Packed$EMPTY - 表示一个空的记分板。
  • net.minecraft.world.waypoints.Waypoint$Icon#copyFrom - 从另一个图标复制图标颜色和样式。

变更列表

  • com.mojang.blaze3d.platform.Lighting#updateLevel 现在接受 DimensionType$CardinalLightType 而不是一个布尔值,表示等级是否不是下界
  • com.mojang.blaze3d.systems.GpuDevice#createTexture 现在有一个接受提供的标签而不是原始字符串的重载
  • com.mojang.blaze3d.vertex.VertexConsumer
    • addVertexaddVertexWith2DPose 现在接受其参数的接口、“只读”变体(例如,Vector3f -> Vector3fc
    • putBulkData 不再接受最后的 boolean 来读取缓冲区数据以确定初始颜色
  • com.mojang.math
    • OctahedralGroup
      • fromXYAngles -> Quadrant#fromXYAngles
      • permute -> SymmetricGroup3#permuteAxis
    • SymmetricGroup3
      • permutation -> permute
      • permuteVector -> OctahedralGroup#rotate
    • Transformation 现在接受其参数的接口、“只读”变体(例如,Vector3f -> Vector3fc
      • 这也适用于参数获取器方法
  • net.minecraft
    • FileUtil#isValidStrictPathSegment -> containsAllowedCharactersOnly,现在是私有的
      • isValidPathSegment 取代
    • Minecraft
      • disconnectWithProgressScreen 现在接受一个 boolean,表示是否停止声音引擎
      • disconnect 现在接受一个 boolean,表示是否停止声音引擎
    • SharedConstants
      • DEBUG_WATER -> DebugScreenEntries#VISUALIZE_WATER_LEVELS,不是一对一
      • DEBUG_HEIGHTMAP -> DebugScreenEntries#VISUALIZE_HEIGHTMAP,不是一对一
      • DEBUG_COLLISION -> DebugScreenEntries#VISUALIZE_COLLISION_BOXES,不是一对一
      • DEBUG_SUPPORT_BLOCKS -> DebugScreenEntries#VISUALIZE_ENTITY_SUPPORTING_BLOCKS,不是一对一
      • DEBUG_LIGHT -> DebugScreenEntries#VISUALIZE_BLOCK_LIGHT_LEVELSVISUALIZE_SKY_LIGHT_LEVELS;不是一对一
      • DEBUG_SKY_LIGHT_SECTIONS -> DebugScreenEntries#VISUALIZE_SKY_LIGHT_SECTIONS,不是一对一
      • DEBUG_SOLID_FACE -> DebugScreenEntries#VISUALIZE_SOLID_FACES,不是一对一
      • DEBUG_CHUNKS -> DebugScreenEntries#VISUALIZE_CHUNKS_ON_SERVER,不是一对一
  • net.minecraft.advancements.criterion.EntityFlagsPredicate 现在接受可选的布尔值,表示实体是否在水中或坠落飞行
    • 关联的 $Builder 方法也已添加
  • net.minecraft.client
    • Camera
      • setup 现在接受 Level 而不是 BlockGetter
      • get* 已被其记录替代(例如,getEntity -> entity
      • Vector3f 返回值被 Vector3fc 取代
    • GraphicsStatus -> GraphicsPreset,不是一对一
    • KeyMapping 现在有一个接受排序顺序的重载
    • MouseHandler#lastClickTime -> lastClick,现在是私有的,不是一对一
    • OptionInstance$OptionInstanceSliderButton 现在实现 ResettableOptionWidget
    • Options
      • graphicsMode -> graphicsPresetapplyGraphicsPreset
      • showNowPlayingToast -> musicToast,不是一对一
  • net.minecraft.client.data.models
    • EquipmentAssetProvider#humanoidAndHorse -> humanoidAndMountArmor
    • ItemModelGenerators
      • getSpans -> getSideFaces,不是一对一
      • $SpanFacing -> $SideDirection,不是一对一
      • $Span -> $SideFace,不是一对一
    • ItemModelOutput#accept 现在有一个接受 ClientItem$Properties 的重载
  • net.minecraft.client.gui
    • Font#NO_SHADOW -> Style#NO_SHADOW
    • GuiGraphics
      • textHighlight 现在接受一个 boolean,表示是否渲染背景矩形
      • submitOutline -> renderOutline
  • net.minecraft.client.gui.components
    • AbstractButton#handleCursor -> handleCursor,现在是 protected
    • AbstractSliderButton
      • HANDLE_WIDTH 现在是 protected
      • canChangeValuesetValue 现在是 protected
    • AbstractWidget#message 现在是 protected
    • CycleButton 现在实现 ResettableOptionWidget
      • builder 现在有一个接受提供的默认值的重载
      • booleanBuilder 现在接受一个布尔值来选择默认使用哪个组件
      • $Builder 现在接受一个提供的默认值
        • displayOnlyValue(boolean) -> displayState,不是一对一
    • FocusableTextWidget 构造函数现在是包私有的,请使用 builder
    • OptionsList 现在将 $AbstractEntry 传递到泛型,而不是 $Entry
      • addSmall 现在有一个接受 OptionInstance 的重载
      • $Entry 现在扩展 $AbstractEntry
      • $OptionEntry 类已移除
        • big -> $Entry#big
        • small -> $Entry#small
    • StringWidget#clipText 现在是公开的静态方法,接受 Font
  • net.minecraft.client.gui.components.debug
    • DebugScreenEntryList
      • toggleF3Visible -> toggleDebugOverlay
      • setF3Visible -> setOverlayVisible
      • isF3Visible -> isOverlayVisible
    • DebugScreenEntryStatus#IN_F3 -> IN_OVERLAY
  • net.minecraft.client.gui.components.debugchart.AbstractDebugChart#COLOR_GREY -> CommonColors#TEXT_GRAY
  • net.minecraft.client.gui.components.toasts.ToastManager
    • createNowPlayingToast -> initializeMusicToast,现在是私有的,不是一对一
    • removeNowPlayingToast -> setMusicToastDisplayState,不是一对一
  • net.minecraft.client.gui.navigation.ScreenRectangle#transform* 方法现在接受其参数的接口、“只读”变体(例如,Vector3f -> Vector3fc
  • net.minecraft.client.gui.render.state.* 现在接受其 pose 的接口、“只读”变体(例如,Vector3f -> Vector3fc
    • GuiTextRenderState 现在接受是否绘制每个字形周围的空白区域
  • net.minecraft.client.gui.screens
    • DeathScreen 现在接受 LocalPlayer
    • Screen 现在有一个接受要使用的 Minecraft 实例和 Font 的重载
      • minecraft 现在是 final
      • font 现在是 final
      • init(Minecraft, int, int) -> init(int, int)
      • resize(Minecraft, int, int) -> init(int, int)
      • handleComponentClicked -> ChatScreen#handleComponentClicked,现在是私有的
      • handleClickEvent 已移至其关联的类,而不是一个超接口(例如,BookViewScreen#handleClickEvent
  • net.minecraft.client.gui.screens.advancements
    • AdvancementsScreen#renderWindow 现在接受鼠标 XY int
    • AdvancementTab#drawTab 现在接受鼠标 XY int
  • net.minecraft.client.gui.screens.debug.DebugOptionsScreen$OptionList 现在是公开的
  • net.minecraft.client.gui.screens.inventory
    • AbstractCommandBlockEditScreen#populateAndSendPacket 不再接受 BaseCommandBlock
    • AbstractContainerScreen#renderSlotsrenderSlot 现在接受鼠标 XY int
    • CreativeModeInventoryScreen#renderTabButton 现在接受鼠标 XY int
    • EffectsInInventory#renderEffects -> render
    • HorseInventoryScreen 现在扩展 AbstractMountInventoryScreen
    • MinecartCommandBlockEditScreen 现在接受 MinecartCommandBlock 而不是 BaseCommandBlock
  • net.minecraft.client.gui.screens.multiplayer.ServerSelectionList$OnlineServerEntry 现在实现 SelectableEntry
  • net.minecraft.client.gui.screens.packs.TransferableSelectionList$PackEntry 现在实现 SelectableEntry
  • net.minecraft.client.gui.screens.recipebook
    • RecipeBookComponent#initFilterButtonTextures -> getFilterButtonTextures,不是一对一
    • RecipeBookTabButton 现在实现 ImageButton 而不是 StateSwitchingButton
      • 构造函数现在接受 XY 位置以及 Button$OnPress 消费者
  • net.minecraft.client.gui.screens.worldselection.WorldSelectionList$WorldListEntry 不再是静态的,现在实现 SelectableEntry
  • net.minecraft.client.model
    • AnimationUtils
      • animateCrossbowCharge 现在接受 float 而不是 int
      • animateZombieArms 现在接受 UndeadRenderState 而不是两个 float
    • HumanoidModel
      • setupAttackAnimation 不再接受 float
      • getArm 现在从 protected 变为 public
  • net.minecraft.client.model.geom.ModelPart#getExtentsForGui 现在接受 Consumer<Vector3fc> 而不是集合
  • net.minecraft.client.model.geom.builders.UVPair 现在是一个记录
  • net.minecraft.client.multiplayer
    • MultiPlayerGameMode#isAlwaysFlying -> isSpectator
    • ServerStatusPinger#pingServer 现在接受一个 EventLoopGroupHolder
  • net.minecraft.client.renderer
    • CloudRenderer#render 现在接受游戏时间 long
    • DynamicUniforms#writeTransform$Transform 不再接受线宽 float
    • GameRenderer#setPanoramicMode -> setPanoramicScreenshotParameters,不是一对一
    • GlobalSettingsUniform#update 现在接受 Camera 以及是否使用旋转网格超采样(RGSS)
    • ItemBlockRenderTypes#setFancy -> setCutoutLeaves
    • ItemInHandRenderer 不再接受 ItemRenderer
    • LevelRenderer#isSectionCompiled -> isSectionCompiledAndVisible
    • RenderPipelines
      • LINE_STRIP -> LINESLINES_TRANSLUCENT,不是一对一
      • DEBUG_LINE_STRIP -> DEBUG_POINTS,不是一对一
    • RenderType
      • LINE_STRIPlineStrip -> RenderTypes#LINESLINES_TRANSLUCENTlinesTranslucent;不是一对一
      • debugLineStrip -> debugPoint,不是一对一
    • SkyRenderer 现在接受 TextureManagerAtlasManager
      • extractRenderState 现在接受 Camera 而不是相机位置
      • renderSunMoonAndStars 现在接受 MoonPhase 而不是 int
    • UniformValue
      • $IVec3Uniform 现在接受 Vector3ic 而不是 Vector3i
      • $Vec2Uniform 现在接受 Vector2fc 而不是 Vector2f
      • $Vec3Uniform 现在接受 Vector3fc 而不是 Vector3f
      • $Vec4Uniform 现在接受 Vector4fc 而不是 Vector4f
    • WeatherEffectRenderer#tickRainParticles 现在接受一个 int 作为天气半径
    • WorldBorderRenderer#extract 现在接受一个 float 作为部分刻
  • net.minecraft.client.renderer.blockentity
    • BannerRenderer#getExtents 现在接受 Consumer<Vector3fc> 而不是集合
    • BedRenderer#getExtents 现在接受 Consumer<Vector3fc> 而不是集合
    • BellRenderer#BELL_RESOURCE_LOCATION -> BELL_TEXTURE
    • DecoratedPotRenderer#getExtents 现在接受 Consumer<Vector3fc> 而不是集合
    • EnchantTableRenderer#BOOK_LOCATION -> BOOK_TEXTURE
    • ShulkerBoxRenderer#getExtents 现在接受 Consumer<Vector3fc> 而不是集合
    • TestInstanceRenderer 不再接受 BlockEntityRendererProvider$Context
  • net.minecraft.client.renderer.blockentity.state.BlockEntityWithBoundingBoxRenderState$InvisibleBlockType$STRUCUTRE_VOID -> STRUCTURE_VOID
  • net.minecraft.client.renderer.chunk.ChunkSectionLayer#textureView -> texture,不是一对一
  • net.minecraft.client.renderer.entity.EntityRenderDispatcher 不再接受 ItemRenderer
  • net.minecraft.client.renderer.entity.layers
    • CarriedBLockLayer 不再接受 BlockRenderDispatcher
    • IronGolemFlowerLayer 不再接受 BlockRenderDispatcher
    • ItemInHandLayer#submitArmWithItem 现在接受持有的 ItemStack
  • net.minecraft.client.renderer.entity.state
    • ArmedEntityRenderState
      • *HandItem -> *HandItemState*HandItemStack;不是一对一
      • extractArmedRenderState 现在接受部分刻 float
    • HorseRenderState#bodyArmorItem -> EquineRenderState#bodyArmorItem
    • HumanoidRenderState
      • attackTime -> ArmedEntityRenderState#attackTime
      • ticksUsingItem 现在是一个浮点数
    • IllagerRenderState 现在扩展 UndeadRenderState
      • ticksUsingItem 现在是一个浮点数
    • ZombieRenderState 现在扩展 UndeadRenderState
    • ZombifiedPiglinRenderState 现在扩展 UndeadRenderState
  • net.minecraft.client.renderer.fog.FogRenderer#setupFog 不再接受 boolean
  • net.minecraft.client.renderer.fog.environment
    • AtmosphericFogEnvironment 现在扩展 FogEnvironment 而不是 AirBasedFogEnvironment
    • FogEnvironment#setupFog 不再接受 EntityBlockPos,而是接受 Camera
  • net.minecraft.client.renderer.item.ClientItem$Properties 现在接受一个浮点数,用于更改交换动画的缩放
  • net.minecraft.client.renderer.special.SpecialModelRenderer#getExtents 现在接受 Consumer<Vector3fc> 而不是集合
  • net.minecraft.client.renderer.state.SkyRenderState#moonPhase 现在是 MoonPhase 而不是 int
  • net.minecraft.client.resources.SplashManager
    • prepare 现在返回 Component 列表而不是字符串
    • apply 现在接受 Component 列表而不是字符串
  • net.minecraft.client.resources.model.BlockModelRotation 现在是一个类
    • by -> get,不是一对一
  • net.minecraft.client.resources.sounds
    • RidingHappyGhastSoundInstance -> RidingEntitySoundInstance,不是一对一
    • RidingMinecartSoundInstance 现在扩展 RidingEntitySoundInstance 而不是 AbstractTickableSoundInstance
      • 构造函数现在接受 SoundEvent、最小和最大音量,以及放大器
    • SimpleSoundInstance#forMusic 不再接受音量
  • net.minecraft.client.sounds
    • SoundEngine 不再接受 MusicManager
      • updateCategoryVolume -> refreshCategoryVolume
      • setVolume -> updateCategoryVolume,不是一对一
    • SoundManager 不再接受 MusicManager
      • updateSourceVolume -> refreshCategoryVolume
      • setVolume -> updateCategoryVolume,不是一对一
  • net.minecraft.gametest.framework.GameTestHelper
    • spawn 现在有一个接受 EntitySpawnReason 或三个 int 作为位置的重载
    • assetTrueassetFalseassertValueEqual 现在有一个接受 String 而不是 Component 的重载
    • assertEntityData 现在有一个接受 AABB 边界框的重载
    • getRelativeBounds 现在是公开的
    • assertEntityPosition -> assertEntityPresent,不是一对一
  • net.minecraft.nbt
    • CompoundTag#remove 现在返回被移除的标签
    • NbtUtils#getDataVersion 现在有一个只接受 CompoundTag 的重载
  • net.minecraft.network
    • Connection
      • NETWORK_WORKER_GROUP -> EventLoopGroupHolder#NIO,不是一对一
      • NETWORK_EPOLL_WORKER_GROUP -> EventLoopGroupHolder#EPOLL,不是一对一
      • LOCAL_WORKER_GROUP -> EventLoopGroupHolder#LOCAL,不是一对一
      • connectToServerconnect 现在接受 EventLoopGroupHolder 而不是 boolean
    • FriendlyByteBuf
      • writeVector3f 现在接受 Vector3fc 而不是 Vector3f
      • writeQuaternion 现在接受 Quaternionfc 而不是 Quaternionf
      • DEFAULT_NBT_QUOTA -> NbtAccounter#DEFAULT_NBT_QUOTA
  • net.minecraft.network.codec
    • ByteBufCodecs
      • VECTOR3F 现在使用 Vector3fc 而不是 Vector3f
      • QUATERNIONF 现在使用 Quaternionfc 而不是 Quaternionf
    • StreamCodec#composite 现在有十个和十二个参数变体
  • net.minecraft.network.chat
    • ComponentUtils#mergeStyles 现在有一个接受并返回 Component 的重载
    • MutableComponent 现在是 final
  • net.minecraft.network.protocol.game
    • ClientboundHorseScreenOpenPacket -> ClientboundMountScreenOpenPacket
    • ClientGamePacketListener#handleHorseScreenOpen -> handleMountScreenOpen
    • GamePacketTypes#CLIENTBOUND_HORSE_SCREEN_OPEN -> CLIENTBOUND_MOUNT_SCREEN_OPEN
  • net.minecraft.network.numbers
    • FixedFormat 现在是一个记录
    • StyledFormat 现在是一个记录
  • net.minecraft.network.syncher.EntityDataSerializers
    • VECTOR3 现在使用 Vector3fc 而不是 Vector3f
    • QUATERNION 现在使用 Quaternionfc 而不是 Quaternionf
  • net.minecraft.server
    • MinecraftServer
      • isAllowedToEnterPortal -> ServerLevel#isAllowedToEnterPortal
      • isSpawningMonsters -> ServerLevel#isSpawningMonsters
      • isPvpAllowed -> ServerLevel#isPvpAllowed
      • isCommandBlockEnabled -> ServerLevel#isCommandBlockEnabled
      • isSpawnerBlockEnabled -> ServerLevel#isSpawnerBlockEnabled
      • getGameRules -> ServerLevel#getGameRules
      • isEpollEnabled -> useNativeTransport
    • ServerScoreboard 不再实现其自己的保存数据类型,而是使用打包的 ScoreboardSaveData
      • TYPE -> ScoreboardSavedData#TYPE
  • net.minecraft.server.jsonrpc
    • IncomingRpcMethod 现在接受两个泛型,分别用于请求的参数和结果响应
      • $Builder 现在有无参数和参数函数的构造函数,取代了 $Factory
        • responseparam 现在接受它们的 Schema
    • OutgoingRpcMethod$Factory 现在接受泛型参数和结果
  • net.minecraft.server.jsonrpc.api
    • MethodInfo$Named 现在接受两个泛型,分别用于请求的参数和结果响应
      • PARAMS_CODEC -> paramsTypedCodec,现在是私有的,不是一对一
      • MAP_CODEC -> typedCodec,现在是包私有的,不是一对一
    • ParamInfo 现在接受一个参数的泛型
      • CODEC -> typedCodec,不是一对一
    • ResultInfo 现在接受一个结果响应的泛型
      • CODEC -> typedCodec,不是一对一
    • Schema 现在接受一个其表示类型的泛型
      • 构造函数现在接受一个类型列表而不是一个可选项、一个非可选的属性映射、非可选的枚举值,以及用于序列化类型的编解码器
      • ofTypes 现在有一个接受类型列表的重载
    • SchemaComponent 现在接受一个其表示类型的泛型
  • net.minecraft.server.jsonrpc.security.AuthenticationHandler 现在实现 ChannelDuplexHandler 而不是 ChannelInboundHandlerAdapter
    • 构造函数现在接受一个允许的来源的字符串集合
    • $SecurityCheckResult#allowed 现在有一个重载,指定令牌是否通过 websocket 协议发送
  • net.minecraft.server.level
    • ChunkMap 现在扩展 SimpleRegionStorage 而不是 ChunkStorage
    • ServerLevel#drop 不再返回 boolean
  • net.minecraft.server.network.ServerConnectionListener
    • SERVER_EVENT_GROUP -> EventLoopGroupHolder#NIO,不是一对一
    • SERVER_EPOLL_EVENT_GROUP -> EventLoopGroupHolder#EPOLL,不是一对一
  • net.minecraft.stats.ServerStatsCounter 现在接受 Path 而不是 File
    • parseLocal -> parse,不是一对一
    • toJson 现在返回 JsonElement 而不是 String
  • net.minecraft.util
    • ARGB#lerp -> srgbLerp
    • ExtraCodecs 现在使用其泛型的接口、“只读”变体(例如,Vector3f -> Vector3fc
    • Mth
      • easeInOutSine -> Ease#inOutSine
      • sincos 现在接受 double 而不是 float
      • absMax 现在有使用 intfloat 的重载
    • TriState 现在实现 StringRepresentable
  • net.minecraft.util.profiling.jfr.Percentiles#evaluate 现在有一个接受 int[] 的重载
  • net.minecraft.util.profiling.jfr.parse.JfrStatsResult 现在接受一个 FPS 统计信息
    • tickTimes -> serverTickTimes
  • net.minecraft.util.profiling.jfr.stats.TimedStatSummary#summary 现在返回 TimeStatSummary 的可选值
  • net.minecraft.util.worldupdate.WorldUpgrader
    • $AbstractUpgrader 不再接受泛型
      • createStorage 现在返回 SimpleRegionStorage 而不是泛型
      • tryProcessOnePosition 现在接受 SimpleRegionStorage 而不是泛型
    • $DimensionToUpgrade 不再接受泛型,而是使用 SimpleRegionStorage
  • net.minecraft.world.RandomSequences 不再接受世界种子
    • codec -> CODEC
    • getreset 现在接受世界种子
  • net.minecraft.world.entity
    • Avatar#DATA_PLAYER_MAIN_HAND 现在使用 HumanoidArm 泛型而不是字节
    • Entity#hasImpulse -> needsSync
    • EntityType#loadEntityRecursive 现在接受 EntityProcessor 而不是 Function
    • LivingEntity#invulnerableDuration -> INVULNERABLE_DURATION
    • Mob#playAttackSound -> LivingEntity#playAttackSound
    • NeutralMob
      • TAG_ANGER_TIME -> TAG_ANGER_END_TIME,不是一对一
      • getRemainingPersistentAngerTime -> getPersistentAngerEndTime,不是一对一
      • setRemainingPersistentAngerTime -> setTimeToRemainAngrysetPersistentAngerEndTime;第二个不是一对一
      • getPersistentAngerTargetsetPersistentAngerTarget 现在处理 EntityReference
  • net.minecraft.world.entity.ai.sensing.SensorType#*_TEMPTATIONS -> FOOD_TEMPTATIONS,不是一对一
  • net.minecraft.world.entity.ai.util
    • GoalUtils
      • mobRestricted 现在接受 double 而不是 int
      • isRestricted 现在有一个接受 Vec3 的重载
    • LandRandomPos
      • getPosAway 现在有一个接受额外 double 作为起始/结束弧度的重载
      • generateRandomPosTowardDirection 现在接受 double 而不是 int
    • RandomPos
      • generateRandomDirectionWithinRadians 现在接受 double 作为起始/结束弧度
      • generateRandomPosTowardDirection 现在接受 double 而不是 int
  • net.minecraft.world.entity.animal.equine.AbstractHorse#getInventorySize -> AbstractMountInventoryMenu#getInventorySize
  • net.minecraft.world.entity.monster.Monster#checkMonsterSpawnRules 现在将其类型泛型扩展为 Mob 而不是 Monster
  • net.minecraft.world.entity.monster.skeleton.Bogged#*_ATTACK_INTERVAL -> AbstractSkeleton#INCREASED_*_ATTACK_INTERVAL
  • net.minecraft.world.entity.monster.zombie
    • Husk#checkHuskSpawnRules -> Monster#checkSurfaceMonsterSpawnRules,不是一对一
    • Zombie
      • doUnderWaterConversion 现在接受 ServerLevel
      • convertToZombieType 现在接受 ServerLevel
  • net.minecraft.world.entity.npc.villager
    • AbstractVillager
      • updateTrades 现在接受 ServerLevel
      • addOffersFromItemListings 现在接受 ServerLevel
    • Villager#shouldRestock 现在接受 ServerLevel
    • VillagerTrades$ItemListing#getOffer 现在接受 ServerLevel
  • net.minecraft.world.entity.player.Player
    • openMinecartCommandBlock 现在接受 MinecartCommandBlock 而不是 BaseCommandBlock
    • sweepAttack -> doSweepAttack,现在是私有的,不是一对一
    • respawn -> LocalPlayer#respawn
    • CLIENT_LOADED_TIMEOUT_TIME -> ServerGamePacketListenerImpl#CLIENT_LOADED_TIMEOUT_TIME
    • clientLoadedTimeoutTimertickClientLoadTimeout -> ServerGamePacketListenerImpl#tickClientLoadTimeout
    • hasClientLoaded -> ServerGamePacketListenerImpl#hasClientLoaded
    • setClientLoaded -> ServerGamePacketListenerImpl#markClientLoadedmarkClientUnloadedAfterDeathrestartClientLoadTimerAfterRespawn;不是一对一
  • net.minecraft.world.entity.projectile.Projectile 构造函数现在是 protected 而不是包私有的
  • net.minecraft.world.entity.vehicle.VehicleEntity#shouldSourceDestroy 现在是 protected 而不是包私有的
  • net.minecraft.world.entity.vehicle.minecart
    • AbstractMinecart 现在接受 ServerLevel
    • MinecartCommandBlock$MinecartCommandBase 现在是包私有的
  • net.minecraft.world.inventory.HorseInventoryMenu 现在扩展 AbstractMountInventoryMenu
  • net.minecraft.world.item.component.ItemAttributeModifiers#compute 现在接受 Attribute 持有者
  • net.minecraft.world.item.enchantment.effects.PlaySoundEffect 现在接受一个声音事件列表而不是单个
  • net.minecraft.world.level
    • BaseCommandBlock
      • performCommand 现在接受 ServerLevel 而不是 Level
      • onUpdated 现在接受 ServerLevel
      • createCommandSourceStack 现在接受 ServerLevel
      • $CloseableCommandBlockSource 现在接受 ServerLevel,其构造函数是 protected
    • CollisionGetter#noBlockCollision 现在有一个接受额外 boolean 的重载,表示是否检查液体碰撞。
    • Level#getGameTime -> LevelAccessor#getGameTime
    • LevelAccessor#getCurrentDifficultyAt -> ServerLevelAccessor#getCurrentDifficultyAt
    • LevelTimeAccess#getMoonPhase 现在返回 MoonPhase 而不是 int
  • net.minecraft.world.level.biome
    • AmbientAdditionsSettings 现在是一个记录
    • AmbientMoodSettings 现在是一个记录
    • AmbientParticleSettings 现在是一个记录
  • net.minecraft.world.level.block.entity.BaseContainerBlockEntity#canUnlock -> sendChestLockedNotifications,不是一对一
  • net.minecraft.world.level.border
    • BorderChangeListener#onLerpSize 现在接受一个额外的 long 作为游戏时间
    • WorldBorder 现在可以接受 WorldBorder$Settings
      • getMin*getMax* 现在有一个接受部分刻 float 的重载
      • lerpSizeBetween 现在接受一个额外的 long 作为游戏时间
      • applySettings -> applyInitialSettings,不是一对一
        • 原始行为可以通过将设置传递给构造函数来复制
      • $BorderExtent#getMin*getMax* 现在接受部分刻 float
  • net.minecraft.world.level.chunk.storage
    • RecreatingSimpleRegionStorage 现在接受一个提供的 LegacyTagFixer
    • SimpleRegionStorage 现在接受一个提供的 LegacyTagFixer
      • write 现在有一个接受提供的 CompoundTag 的重载
      • upgradeChunkTag 现在有一个接受可为空的标签上下文的重载
  • net.minecraft.world.level.dimension.DimensionType
    • MOON_PHASES 现在是一个 MoonPhase 数组并且是私有的
    • moonPhase 现在返回 MoonPhase 而不是 int
  • net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler 现在实现 LegacyTagFixer
    • 构造函数现在接受 DataFixer
    • removeIndex -> LegacyTagFixer#markChunkDone
    • updateFromLegacy 现在是私有的
    • getLegacyStructureHandler 现在接受 DataFixer、一个提供的 DimensionDataStorage,并返回一个提供的 LegacyTagFixer
  • net.minecraft.world.level.levelgen.structure.structures.NetherFortressPieces$StartPiece 字段现在是包私有的
  • net.minecraft.world.level.saveddata.SavedDataType 不再接受 SavedData$Context,移除了函数参数构造函数
  • net.minecraft.world.level.storage
    • DimensionDataStorage 不再接受 SavedData$Context
    • FileNameDateFormatter#create -> FORMATTER
    • LevelStorageSource
      • UNCOMPRESSED_NBT_QUOTA -> NbtAccounter#UNCOMPRESSED_NBT_QUOTA,现在是 public
      • $LevelDirectory#corruptedDataFilerawDataFile 现在接受 ZonedDateTime 而不是 LocalDateTime
  • net.minecraft.world.level.storage.loot.LootContext
    • $BlockEntityTarget 现在实现 LootContextArg$SimpleGetter
      • getParam -> contextParam
    • $EntityTarget 现在实现 LootContextArg$SimpleGetter
      • getParam -> contextParam
    • $ItemStackTarget 现在实现 LootContextArg$SimpleGetter
      • getParam -> contextParam
  • net.minecraft.world.level.storage.loot.functions
    • CopyComponentsFunction
      • $*Source -> $DirectSource,不是一对一
      • $Source -> LootContextArg$Getter,不是一对一
    • CopyNameFunction#copyName 现在接受 LootContextArg 而不是 $Source
      • $Source -> LootContextArg,不是一对一
    • FilteredFunction 现在接受一个可选的通过和失败的 LootItemFunction 而不是仅仅一个修改器
      • 该函数现在可以通过 $Builder 通过 filtered 构建
  • net.minecraft.world.phys.Vec3 现在接受 Vector3fc 而不是 Vector3f
  • net.minecraft.world.phys.shapes.Shapes#rotateHorizontalrotateAllrotateAttachFace 现在有接受 OctahedralGroup 的重载
  • net.minecraft.world.scores
    • Score 现在有一个用于 $Packed 值的公共构造函数
      • MAP_CODEC -> Score$Packed 及其 $Packed#MAP_CODEC
    • Scoreboard$PackedScore#score 现在接受 Score$Packed 而不是 Score
    • ScoreboardSavedData 现在接受 ScoreboardSaveData$Packed 而不是 Scoreboard
      • FILE_ID 合并到类型中
      • loadFrom -> ServerScoreboard#load
      • pack -> ServerScoreboard#store,现在是私有的,不是一对一

移除列表

  • com.mojang.blaze3d.vertex.VertexFormat$Mode#LINE_STRIP
  • net.minecraft.Util#lastOf
  • net.minecraft.client
    • Minecraft#useFancyGraphics
    • GuiMessage#icon
    • StringSplitter
      • formattedIndexByWidthcomponentStyleAtWidth
      • splitLines(FormattedText, int, Style, FormattedText)
  • net.minecraft.client.gui.Font#wordWrapHeight(String, int)
  • net.minecraft.client.gui.components
    • CycleButton
      • onOffBuilder()
      • $Builder#withInitialValue
    • StateSwitchingButton
  • net.minecraft.client.gui.screens.inventory
    • EffectsInInventory#renderTooltip
    • InventoryScreen#renderEntityInInventory
  • net.minecraft.client.gui.screens.packs.PackSelectionScreen#clearSelected
  • net.minecraft.client.player.LocalPlayer#USING_ITEM_SPEED_FACTOR
  • net.minecraft.client.renderer
    • ItemModelGenerator#createOrExpandSpan
    • GpuWarnlistManager#dismissWarningAndSkipFabulousisSkippingFabulous
    • RenderPipelines
      • DEBUG_STRUCTURE_QUADSDEBUG_SECTION_QUADS
    • SkyRenderer#initTextures
  • net.minecraft.client.renderer.fog.environment
    • AirBasedFogEnvironment
    • DimensionOrBossFogEnvironment
    • FogEnvironment#onNotApplicable
  • net.minecraft.client.resources.model.BlockModelRotation#actualRotation
  • net.minecraft.gametest.framework.GameTestHelper#setNightsetDayTime
  • net.minecraft.network.FriendlyByteBuf#readDatewriteDate
  • net.minecraft.server
    • MinecraftServer#hasGui
    • ServerScoreboard#createDataaddDirtyListener
  • net.minecraft.server.jsonrpc.IncomingRpcMethod$Factory
  • net.minecraft.server.jsonrpc.methods.IllegalMethodDefinitionException
  • net.minecraft.server.jsonrpc.security.AuthenticationHandler#AUTH_HEADER
  • net.minecraft.util
    • DebugBuffer
    • LazyLoadedValue
  • net.minecraft.util.thread.NamedThreadFactory
  • net.minecraft.world.entity.Mob#isSunBurnTick
  • net.minecraft.world.entity.animal.armadillo.ArmadilloAi#getTemptations
  • net.minecraft.world.entity.animal.axolotl.AxolotlAi#getTemptations
  • net.minecraft.world.entity.animal.camel.CamelAi#getTemptations
  • net.minecraft.world.entity.animal.equine.ZombieHorse#checkZombieHorseSpawnRules
    • 请改用 Monster#checkMonsterSpawnRules
  • net.minecraft.world.entity.animal.goat.GoatAi#getTemptations
  • net.minecraft.world.entity.animal.sniffer.SnifferAi#getTemptations
  • net.minecraft.world.entity.player.Player#playNotifySound
  • net.minecraft.world.entity.raid.Raid#TICKS_PER_DAY
  • net.minecraft.world.level
    • BaseCommandBlock
      • getLevel
      • getUsedBygetPosition
    • Level#TICKS_PER_DAY
  • net.minecraft.world.level.border.WorldBorder$Settings#toWorldBorder
    • 请改用 WorldBorder 构造函数
  • net.minecraft.world.level.chunk.storage
    • ChunkStorage
    • RecreatingChunkStorage
  • net.minecraft.world.level.saveddata.SavedData$Context
  • net.minecraft.world.phys.Vec3#fromRGB24

Minecraft 1.21.11 向 26.1 版本模组迁移指南

本文是关于如何将模组从1.21.11版本迁移至26.1版本的高层次概览(非详尽说明)。内容不针对特定模组加载器,仅涉及原版类的变更。

本指南采用知识共享署名4.0国际许可协议授权,欢迎作为参考资料使用,使用时请保留原文链接以便其他读者查阅。

若发现任何错误或遗漏信息,请在本代码库提交issue,或在Neoforged Discord服务器中@ChampionAsh5357。

特别鸣谢:

  • @Shnupbups 的语法修正
  • @cassiancc 提供的Java 25 IDE支持信息
  • @boq 关于输入法支持的信息
  • @lolothepro 发现的拼写错误

资源包变更

原版还存在许多面向用户的改动未在本文讨论,这些内容可能对模组开发者具有参考价值。具体变更清单可查看Misode的版本更新日志

Java 25 与反混淆

26.1 在通用流程中引入了两项新变化。

首先,Java 开发工具包已从 21 升级到 25。原版使用了这些新特性,例如 JEP 447,它允许在构造函数中在 super 之前使用语句。对于模组开发社区的用户,请确保相应更新,或利用您的 IDE 或构建工具功能。Microsoft 的 OpenJDK 可以在此处找到。

您可能需要更新 IDE 以支持 Java 25。如果使用 Eclipse,您至少需要 2025-12 版本,或者使用 Java 25 支持市场插件的 2025-09 版本。如果使用 IntelliJ IDEA,您至少需要 2025.2 版本。

原版也已回归到反混淆状态,这意味着所有值类型现在都具有 Mojang 提供的官方名称。由于 Java 编译过程,仍然有一些内容未被捕获,例如内联原始类型和字符串常量,但大部分现已提供。这对于使用不同于官方映射的值类型映射集的用户或模组加载器来说将产生影响。

战利品类型展开

战利品池条目、物品函数、物品条件、NBT 提供者、数字提供者、分数提供者、整数提供者和浮点数提供者不再使用包装对象类型作为注册实例。现在,注册表直接接受用于序列化和反序列化过程的 MapCodec。因此,持有编解码器的 *Type 类或记录已被移除。此外,getType 现已重命名为 codec,接受注册的 MapCodec

// 以下是一个 LootItemFunction 的示例,但大致也适用于其他实例

public record NoopItemFunction() implements LootItemFunction {
    public static final NoopItemFunction INSTANCE = new NoopItemFunction();
    // 用作注册表对象的映射编解码器
    public static final MapCodec<NoopItemFunction> MAP_CODEC = MapCodec.unit(INSTANCE);

    // 取代 getType
    @Override
    public MapCodec<NoopItemFunction> codec() {
        // 返回注册表对象
        return MAP_CODEC;
    }
}

// 将映射编解码器注册到适当的注册表
Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, Identifier.fromNamespaceAndPath("examplemod", "noop"), NoopItemFunction.MAP_CODEC);
  • net.minecraft.core.registries.BuiltInRegistriesRegistries
    • LOOT_POOL_ENTRY_TYPE 现在持有 LootPoolEntryContainer 的映射编解码器,而不是 LootPoolEntryType
    • LOOT_FUNCTION_TYPE 现在持有 LootItemFunction 的映射编解码器,而不是 LootItemFunctionType
    • LOOT_CONDITION_TYPE 现在持有 LootItemCondition 的映射编解码器,而不是 LootItemConditionType
    • LOOT_NUMBER_PROVIDER_TYPE 现在持有 NumberProvider 的映射编解码器,而不是 LootNumberProviderType
    • LOOT_NBT_PROVIDER_TYPE 现在持有 NbtProvider 的映射编解码器,而不是 LootNbtProviderType
    • LOOT_SCORE_PROVIDER_TYPE 现在持有 ScoreboardNameProvider 的映射编解码器,而不是 LootScoreProviderType
    • FLOAT_PROVIDER_TYPE 现在持有 FloatProvider 的映射编解码器,而不是 FloatProviderType
    • INT_PROVIDER_TYPE 现在持有 IntProvider 的映射编解码器,而不是 IntProviderType
  • net.minecraft.util.valueproviders 现在将 CODEC 字段重命名为 MAP_CODEC
    • FloatProvider 的子类型现在都是记录
    • IntProvider 的子类型,除了 WeightedListInt,现在都是记录
    • FloatProvider 现在从 class 变为 interface
      • CODEC -> FloatProviders#CODEC
      • codec -> FloatProviders#codec
      • getType -> codec,不是一对一
      • getMinValue -> min
      • getMaxValue -> max
    • FloatProviders - 所有要注册的原版浮点数提供者。
    • FloatProviderType 接口已移除
      • 所有单例字段已被移除,请改用每个类中的映射编解码器
      • codec -> FloatProvider#codec
    • IntProvider 现在从 class 变为 interface
      • CODEC -> IntProviders#CODEC
      • NON_NEGATIVE_CODEC -> IntProviders#NON_NEGATIVE_CODEC
      • POSITIVE_CODEC -> IntProviders#POSITIVE_CODEC
      • codec -> IntProviders#codec
      • validateCodec -> IntProviders#validateCodec
      • getMinValue -> minInclusive
      • getMaxValue -> maxInclusive
      • getType -> codec,不是一对一
    • IntProviders - 所有要注册的原版整数提供者。
    • IntProviderType 接口已移除
      • 所有单例字段已被移除,请改用每个类中的映射编解码器
      • codec -> IntProvider#codec
  • net.minecraft.world.level.storage.loot.entries 现在将 CODEC 字段重命名为 MAP_CODEC
    • LootPoolEntries 的所有单例字段已被移除
      • 应改用每个类中的映射编解码器
      • bootstrap - 注册战利品池条目。
    • LootPoolEntryContainer#getType -> codec,不是一对一
    • LootPoolEntryType 记录已移除
  • net.minecraft.world.level.storage.loot.functions 现在将 CODEC 字段重命名为 MAP_CODEC
    • LootItemFunction#getType -> codec,不是一对一
    • LootItemFunctions 的所有单例字段已被移除
      • 应改用每个类中的映射编解码器
      • bootstrap - 注册战利品物品函数。
    • LootItemFunctionType 记录已移除
  • net.minecraft.world.level.storage.loot.predicates 现在将 CODEC 字段重命名为 MAP_CODEC
    • LootItemCondition#getType -> codec,不是一对一
    • LootItemConditions 的所有单例字段已被移除
      • 应改用每个类中的映射编解码器
      • bootstrap - 注册战利品物品条件。
    • LootItemConditionType 记录已移除
  • net.minecraft.world.level.storage.loot.providers.nbt 现在将 CODEC 字段重命名为 MAP_CODEC
    • LootNbtProviderType 记录已移除
    • NbtProvider 现在实现 LootContextUser
      • getType -> codec,不是一对一
    • NbtProviders 的所有单例字段已被移除
      • 应改用每个类中的映射编解码器
      • bootstrap - 注册 NBT 提供者。
    • LootItemConditionType 记录已移除
  • net.minecraft.world.level.storage.loot.providers.number 现在将 CODEC 字段重命名为 MAP_CODEC
    • LootNumberProviderType 记录已移除
    • NumberProvider#getType -> codec,不是一对一
    • NumberProviders 的所有单例字段已被移除
      • 应改用每个类中的映射编解码器
      • bootstrap - 注册数字提供者。
  • net.minecraft.world.level.storage.loot.providers.score 现在将 CODEC 字段重命名为 MAP_CODEC
    • LootScoreProviderType 记录已移除
    • ScoreProvider 现在实现 LootContextUser
      • getType -> codec,不是一对一
    • ScoreProviders 的所有单例字段已被移除
      • 应改用每个类中的映射编解码器
      • bootstrap - 注册分数提供者。

验证大修

用于收集然后报告数据生成内容问题的验证处理程序已被大修。这从来就不是字段验证的替代品。验证处理程序专门用于更方便地处理多个信息之间的验证,这些信息可能无法暴露给单个字段,例如战利品提供者是否可用于给定的上下文参数。

所有经过验证的对象都实现 Validatable,或者专门针对进度条件的 CriterionTriggerInstance。这两种方法都提供一个方法:validate,用于检查对象的有效性。validate 接受一个 ValidationContext,它本质上持有用于收集问题的 ProblemReporter、当前上下文参数以及一个引用解析器。CriterionTriggerInstance 提供一个 ValidationContextSource,但可以使用 context 方法之一将其转换为 ValidationContext,提供要检查的上下文参数。如果无法验证特定对象,则调用 ValidationContext#reportProblem,详细说明具体问题。

// 对于某个实现 Validatable 的对象

@Override
public void validate(ValidationContext ctx) {
    // 检查特定条件是否通过验证。
    if (this.foo() != this.bar()) {
        // 如果没有,则报告存在问题。
        ctx.reportProblem(() -> "'Foo' 不等于 'bar'。");
    }
}

如果对象本身没有问题,而是特定字段有问题,那么报告器可以在检查各个元素时跟踪堆栈跟踪,使用 ValidationContext#for* 方法之一,执行类似操作。

// 对于某个实现 Validatable 的对象
// 假设它有一个子对象列表。

@Override
public void validate(ValidationContext ctx) {
    for (int i = 0; i < this.children.size(); i++) {
        // 获取列表中子项的特定上下文
        var childCtx = ctx.forIndexedField("children", i);
        // 检查特定条件是否通过验证。
        if (this.foo() != this.bar()) {
            // 如果没有,则报告存在问题。
            childCtx.reportProblem(() -> "'Foo' 不等于 'bar'。");
        }
    }
}

Validatable 还提供了一些用于检查其他 Validatable 字段的静态实用程序。

// 对于某个实现 Validatable 的对象
// 假设某个子对象也实现了 Validatable

@Override
public void validate(ValidationContext ctx) {
    Validatable.validate(ctx, "child", this.child);
}

在所有必需的对象上实现 Validatable 后,可以根据使用位置(通常在反序列化之后或序列化之前)调用验证。这些的调用堆栈通常如下:

// 对于某个 Validatable validatable
// 假设我们可以访问 HolderGetter.Provider provider。
// 如果不可用,参数本身是可选的。

// 创建问题收集器和验证上下文。
// 上下文参数应仅包括正在提供的参数。
ProblemReporter reporter = new ProblemCollector.Collector();
ValidationContext ctx = new ValidationContext(reporter, LootContextParamSets.ALL_PARAMS, provider);

// 调用验证器
validatable.validate(ctx);

这也可以通过 Codec#validate 附加到编解码器的末尾:

public record ExampleObject() implements Validatable {
    public static final Codec<ExampleObject> CODEC = MapCodec.unitCodec(
        ExampleObject::new
    ).validate(
        // 提供验证器以及要检查的上下文参数。
        // 此方法无法访问注册表提供者。
        Validatable.validatorForContext(LootContextParamSets.ALL_PARAMS)
    );

    @Override
    public void validate(ValidationContext ctx) {
        // ...
    }
}
  • net.minecraft.advancements.CriterionTriggerInstance#validate 现在接受 ValidationContextSource 而不是 CriterionValidator
  • net.minecraft.advancements.criterion
    • ContextAwarePredicate 现在实现 Validatable
    • CriterionValidator -> ValidationContextSourceValidatable
      • Validatable 包含 validate* 方法
      • ValidationContextSource 持有上下文和报告器
  • net.minecraft.world.item.enchantment
    • ConditionalEffect 现在实现 Validatable
      • conditionCodec 被加载后调用 validate 取代
    • TargetedConditionalEffect 现在实现 Validatable
  • net.minecraft.world.level.storage.loot
    • IntRange 现在实现 LootContextUser
      • getReferencedContextParamsvalidate 取代
    • LootContext$VisitedEntry 泛型现在必须扩展 Validatable
    • LootContextUser 现在实现 Validatable
    • LootDataType 泛型现在必须扩展 Validatable
      • 构造函数现在接受 $ContextGetter 而不是 $Validator
      • runValidation 现在接受 ValidationContextSource 而不是 ValidationContext
        • 还有一个接受 HolderLookup 而不是键值对的重载
      • createSimpleValidatorcreateLootTableValidator$ValidatorValidatable 取代
      • $ContextGetter - 获取某个值的 ContextKeySet
    • LootPool 现在实现 Validatable
    • LootTable 现在实现 Validatable
    • Validatable - 一个接口,处理其实例在给定上下文中的验证。
    • ValidationContext
      • forField - 为给定字段创建上下文。
      • forIndexedField - 为列表中的给定条目创建上下文。
      • forMapField - 为映射中的给定键创建上下文。
      • setContextKeySet 已移除
    • ValidationContextSource - 进行验证的定义上下文的源。
  • net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer 现在实现 Validatable
  • net.minecraft.world.level.storage.loot.functions
    • SetAttributesFunction$Modifier 现在实现 LootContextUser
    • SetStewEffectFunction$EffectEntry 现在实现 LootContextUser

数据包村民交易

村民交易现已从其原始的基于映射的设置变为数据生成的注册表。虽然初步印象可能使该系统看起来更受限,但实际上它同样具有可扩展性,尽管方式相当复杂,因为交易本身就是一个战利品表,用于确定商人可以提供哪些 MerchantOffer。为了便于理解,本节将介绍交易重写的基础知识,以及如何将每个先前的物品列表转换为 VillagerTrade

理解交易格式

所有交易都表示为 VillagerTrade,其核心是确定商人 wants(想要)什么以及它 gives(给予)什么作为回报。每个交易还可以提供对物品本身或其成本的修改器,或者根据给定条件决定是否可以达成特定交易。每个交易还指定可以进行的交易次数、给予多少经验值,或者与用户声誉相乘的价格倍数。然后通过 getOfferVillagerTrade 转换为 MerchantOffer,接受 LootContext,通常带有上下文参数 LootContextParamSets#VILLAGER_TRADE,提供商人本身(THIS_ENTITY)及其位置(ORIGIN)。

交易本身位于 data/<namespace>/villager_trade/<path>。通常,路径包含职业和交易等级,例如 examplemod:example_profession/1/example_trade

// 对于某个村民交易 'examplemod:example_profession/1/example_trade'
// JSON 位于 'data/examplemod/villager_trade/example_profession/1/example_trade.json'
{
    // 商人想要的堆栈。
    "wants": {
        // 堆栈的物品。
        "id": "minecraft:apple",
        // 一个数字提供者,用于确定想要多少该物品。一旦确定了数量,
        // `gives` 堆栈上的任何额外成本(通过 `ADDITIONAL_TRADE_COST` 组件)
        // 将在钳制到最大堆栈大小之前添加到数量中。
        // 如果未指定,默认为 1。
        "count": {
            "type": "minecraft:uniform",
            "min": 1,
            "max": 5
        },
        // 堆栈应具有的任何组件。堆栈必须具有确切指定的组件。
        // 如果未指定,则不会检查任何组件,这意味着此项被忽略。
        "components": {
            // 注册表键到组件值的映射。
            "minecraft:custom_name": "苹果...?"
        }
    },
    // 商人额外想要的一个堆栈。
    // 如果未指定,商人只检查 `wants`。
    "additional_wants": {
        "id": "minecraft:emerald"
    },
    // 商人给予的堆栈模板。
    "gives": {
        // 堆栈的物品。
        "id": "minecraft:golden_apple",
        // 一个数字 [1, 99]。
        // 如果未指定,默认为 1。
        "count": 1,
        // 要应用于堆栈的组件。
        // 如果未指定,则仅应用默认的物品组件。
        "components": {
            "minecraft:custom_name": "不是苹果"
        }
    },
    // 一个数字提供者,用于确定玩家在商人补货之前可以进行交易的次数。
    // 该值将至少为 1。
    // 如果未指定,默认为 4。
    "max_uses": {
        "type": "minecraft:uniform",
        "min": 1,
        "max": 20
    },
    // 一个数字提供者,用于确定根据玩家与商人的声誉以及物品需求
    // 应用于物品成本的价格乘数,该乘数根据玩家进行交易的次数计算。
    // 这通常应该是一个小数,因为用户每个商人的最大声誉是 150,
    // 尽管用户最多更可能拥有 25 的声誉。
    // 然而,即使声誉折扣乘以声誉表示 100% 或更多折扣,
    // 交易也必须始终至少有一个物品。
    // 如果未指定,默认为 0。
    "reputation_discount": {
        "type": "minecraft:uniform",
        "min": 0,
        "max": 0.05
    },
    // 一个数字提供者,用于确定玩家与商人进行交易获得的经验值。
    // 对于原版交易,这通常在 5-30 经验值左右。
    // 如果未指定,默认为 1。
    "xp": {
        "type": "minecraft:uniform",
        "min": 10,
        "max": 20
    },
    // 一个战利品物品条件,确定商人是否可以向玩家提供此交易。
    // 如果未指定,默认为始终为 true。
    "merchant_predicate": {
        // 此交易只能由来自沙漠或雪地村庄的村民执行。
        "condition": "minecraft:entity_properties",
        "entity": "this",
        "predicate": {
            "predicates": {
                "minecraft:villager/variant": [
                    "minecraft:desert",
                    "minecraft:snow"
                ]
            }
        }
    },
    // 一个战利品物品函数列表,用于修改从 `gives` 提供给玩家的物品。
    // 如果未指定,`gives` 不会被修改。
    "given_item_modifiers": [
        {
            // 从提供的标签中选择一个随机附魔
            "function": "minecraft:enchant_randomly",
            // 如果为 true,则交易成本增加所需的 `wants` 物品数量。
            "include_additional_cost_component": true,
            "only_compatible": false,
            "options": "#minecraft:trades/desert_common"
        }
    ],
    // 可以是一个附魔 id,例如 "minecraft:protection",
    // 或一个附魔 id 列表,例如 ["minecraft:protection", "minecraft:smite", ...],
    // 或一个附魔标签,例如 "#minecraft:trades/desert_common"。
    // 当提供时,如果 `gives` 物品在修饰后包含此列表中的附魔,
    // 则所需的 `wants` 物品数量乘以 2。
    // 如果未指定,则不执行任何操作。
    "double_trade_price_enchantments": "#minecraft:trades/desert_common"
}

商人的交易

每个商人都可以进行许多交易,通常从称为 TradeSet 的指定池中选择。交易集本身是一个单独的数据包注册表,它使用 VillagerTrade。每组交易决定可以提供多少交易以及是否可以多次选择相同的交易。提供的交易在 AbstractVillager#addOffersFromTradeSet 中计算,首先调用 TradeSet#calculateNumberOfTrades 获取报价数量,然后使用 AbstractVillager#addOffersFromItemListingsAbstractVillager#addOffersFromItemListingsWithoutDuplicates 来选择要使用的报价。

请注意,如果允许重复交易,则存在潜在的竞争条件,如果所有交易的 merchant_predicate 都失败,则报价将永远循环。这是因为该方法总是假设至少存在一个可以进行的交易。

交易集位于 data/<namespace>/trade_set/<path>。通常,路径包含职业和交易等级,例如 examplemod:example_profession/level_1.json

// 对于某个交易集 'examplemod:example_profession/level_1'
// JSON 位于 'data/examplemod/villager_trade/trade_set/level_1.json'
{
    // 可以是一个村民交易 id,例如 "examplemod:example_profession/1/example_trade",
    // 或一个交易 id 列表,例如 ["examplemod:example_profession/1/example_trade", "minecraft:farmer/1/wheat_emerald", ...],
    // 或一个交易标签,例如 "#examplemod:example_profession/level_1"。
    // 这是商人可以提供的交易集合。
    // 这应该始终是一个村民交易标签,以便其他用户
    // 可以轻松地将自己的交易添加到商人。
    "trades": "#examplemod:example_profession/level_1",
    // 一个数字提供者,用于确定商人可以提供的报价数量。
    "amount": {
        "type": "minecraft:uniform",
        "min": 1,
        "max": 5
    },
    // 是否可以使用相同的交易进行多个报价。
    // 如果未指定,默认为 false。
    "allow_duplicates": true,
    // 一个标识符,用于确定在确定报价时要使用的唯一随机实例。
    // 如果未指定,则使用等级随机。
    "random_sequence": "examplemod:example_profession/level_1"
}

村民交易标签可以是:

// 对于某个标签 'examplemod:example_profession/level_1'
// JSON 位于 'data/examplemod/tags/villager_trade/example_profession/level_1.json'
{
    "values": [
        "examplemod:example_profession/1/example_trade"
    ]
}

这也意味着可以通过添加到关联的标签来轻松地将交易添加到现有的交易集中:

// 对于某个标签 'minecraft:farmer/level_1'
// JSON 位于 'data/minecraft/tags/villager_trade/farmer/level_1.json'
{
    "values": [
        "examplemod:example_profession/1/example_trade"
    ]
}

同时,通过将等级 int 映射到 tradeSetsByLevel 中的交易集键来添加到新的 VillagerProfession

public static final VillagerProfession EXAMPLE = Registry.register(
    BuiltInRegistries.VILLAGER_PROFESSION,
    Identifier.fromNamespaceAndPath("examplemod", "example_profession"),
    new VillagerProfession(
        Component.literal(""),
        p -> true,
        p -> true,
        ImmutableSet.of(),
        ImmutableSet.of(),
        null,
        // 职业等级到交易集键的映射
        Int2ObjectMap.ofEntries(
            Int2ObjectMap.entry(
                // 职业等级
                1,
                // 交易集 id
                ResourceKey.create(Registries.TRADE_SET, Identifier.fromNamespaceAndPath("examplemod", "example_profession/level_1"))
            )
        )
    )
);

物品列表转换

考虑到所有这些,我们现在可以将物品列表转换为其新的数据生成村民交易。

绿宝石 <-> 物品

对于以下交易:

public static final VillagerTrades.ItemListing ITEM_TO_EMERALD = new VillagerTrades.EmeraldForItems(
    // 商人想要的物品。
    Items.WHEAT,
    // 商人想要的物品数量。
    20,
    // 补货前可以进行的最大交易次数。
    16,
    // 交易给予的经验值。
    2,
    // 给予的绿宝石数量。
    1
);

public static final VillagerTrades.ItemListing EMERALD_TO_ITEM = new VillagerTrades.ItemsForEmeralds(
    // 商人将给予的物品。
    Items.BREAD,
    // 商人想要的绿宝石数量。
    1,
    // 商人将给予的物品数量。
    6,
    // 补货前可以进行的最大交易次数。
    16,
    // 交易给予的经验值。
    1,
    // 应用于报价的价格乘数,考虑声誉和需求。
    0.05f
);

它们的等价形式为:

// 对于某个村民交易 'examplemod:item_to_emerald'
// JSON 位于 'data/examplemod/villager_trade/item_to_emerald.json'
{
    "gives": {
        // 给予的绿宝石数量。
        "count": 1,
        "id": "minecraft:emerald"
    },
    // 补货前可以进行的最大交易次数。
    "max_uses": 16,
    // 应用于报价的价格乘数,考虑声誉和需求。
    // `EmeraldForItems` 将此硬编码为 0.05
    "reputation_discount": 0.05,
    "wants": {
        // 商人想要的物品数量。
        "count": 20,
        // 商人想要的物品。
        "id": "minecraft:wheat"
    },
    // 交易给予的经验值。
    "xp": 2
}


// 对于某个村民交易 'examplemod:emerald_to_item'
// JSON 位于 'data/examplemod/villager_trade/emerald_to_item.json'
{
    "gives": {
        // 商人将给予的物品数量。
        "count": 6,
        // 商人将给予的物品。
        "id": "minecraft:bread"
    },
    // 补货前可以进行的最大交易次数。
    "max_uses": 16,
    // 应用于报价的价格乘数,考虑声誉和需求。
    "reputation_discount": 0.05,
    "wants": {
        "id": "minecraft:emerald",
        // 商人想要的绿宝石数量。
        "count": 1
    },
    // 交易给予的经验值。
    "xp": 1
}

物品和绿宝石 -> 物品

对于以下交易:

public static final VillagerTrades.ItemListing ITEM_EMERALD_TO_ITEM = new VillagerTrades.ItemsAndEmeraldsToItems(
    // 商人想要的物品。
    Items.COD,
    // 商人想要的物品数量。 
    6,
    // 商人额外想要的绿宝石数量。
    1,
    // 商人将给予的物品。
    Items.COOKED_COD,
    // 商人将给予的物品数量。
    6,
    // 补货前可以进行的最大交易次数。
    16,
    // 交易给予的经验值。
    1,
    // 应用于报价的价格乘数,考虑声誉和需求。
    0.05f
);

等价形式为:

// 对于某个村民交易 'examplemod:item_emerald_to_item'
// JSON 位于 'data/examplemod/villager_trade/item_emerald_to_item.json'
{
    // 商人额外想要的绿宝石。
    "additional_wants": {
        "id": "minecraft:emerald",
    },
    "gives": {
        // 商人将给予的物品数量。
        "count": 6,
        // 商人将给予的物品。
        "id": "minecraft:cooked_cod"
    },
    // 补货前可以进行的最大交易次数。
    "max_uses": 16,
    // 应用于报价的价格乘数,考虑声誉和需求。
    "reputation_discount": 0.05,
    "wants": {
        // 商人想要的物品数量。 
        "count": 6,
        // 商人想要的物品。
        "id": "minecraft:cod"
    },
    // 交易给予的经验值。
    "xp": 1
}

绿宝石 -> 染色盔甲

对于以下交易:

public static final VillagerTrades.ItemListing EMERALD_TO_DYED_ARMOR = new VillagerTrades.DyedArmorForEmeralds(
    // 商人将给予并染色的物品。
    Items.LEATHER_HELMET,
    // 商人想要的绿宝石数量。
    5,
    // 补货前可以进行的最大交易次数。
    12,
    // 交易给予的经验值。
    5
);

等价形式为:

// 对于某个村民交易 'examplemod:emerald_to_dyed_armor'
// JSON 位于 'data/examplemod/villager_trade/emerald_to_dyed_armor.json'
{
    "given_item_modifiers": [
        {
            // 在盔甲上设置随机染料。
            "function": "minecraft:set_random_dyes",
            "number_of_dyes": {
                "type": "minecraft:sum",
                "summands": [
                    1.0,
                    {
                        "type": "minecraft:binomial",
                        "n": 2.0,
                        "p": 0.75
                    }
                ]
            }
        },
        {
            // 检查染料是否成功应用于物品。
            "function": "minecraft:filtered",
            "item_filter": {
                "items": "minecraft:leather_helmet",
                "predicates": {
                    "minecraft:dyed_color": {}
                }
            },
            // 如果失败,则丢弃报价。
            "on_fail": {
                "function": "minecraft:discard"
            }
        }
    ],
    "gives": {
        "count": 1,
        // 商人将给予并染色的物品。
        "id": "minecraft:leather_helmet"
    },
    // 补货前可以进行的最大交易次数。
    "max_uses": 12,
    // 应用于报价的价格乘数,考虑声誉和需求。
    "reputation_discount": 0.05,
    "wants": {
        // 商人想要的绿宝石数量。
        "count": 5,
        "id": "minecraft:emerald"
    },
    // 交易给予的经验值。
    "xp": 5
}

绿宝石 -> 附魔物品

对于以下交易:

public static final VillagerTrades.ItemListing EMERALD_TO_ENCHANTED_BOOK = new VillagerTrades.EnchantBookForEmeralds(
    // 交易给予的经验值。
    30,
    // 选择书籍上存储附魔时使用的最小等级。
    3,
    // 选择书籍上存储附魔时使用的最大等级。
    3,
    // 包含可供书籍选择的可用附魔列表的标签。
    EnchantmentTags.TRADES_DESERT_SPECIAL
);

public static final VillagerTrades.ItemListing EMERALD_TO_ENCHANTED_ITEM = new VillagerTrades.EnchantedItemForEmeralds(
    // 商人将给予并尝试附魔的物品。
    Items.FISHING_ROD,
    // 商人想要的绿宝石基础数量。
    3,
    // 补货前可以进行的最大交易次数。
    3,
    // 交易给予的经验值。
    10,
    // 应用于报价的价格乘数,考虑声誉和需求。
    0.2f
);

等价形式为:

// 对于某个村民交易 'examplemod:emerald_to_enchanted_book'
// JSON 位于 'data/examplemod/villager_trade/emerald_to_enchanted_book.json'
{
    // 商人期望一本书来写入附魔。
    "additional_wants": {
        "id": "minecraft:book"
    },
    // 当在双倍交易价格标签中时,绿宝石交易成本增加。
    "double_trade_price_enchantments": "#minecraft:double_trade_price",
    "given_item_modifiers": [
        {
            "function": "minecraft:enchant_with_levels",
            "include_additional_cost_component": true,
            "levels": {
                "type": "minecraft:uniform",
                // 选择书籍上存储附魔时使用的最小等级。
                "min": 3,
                // 选择书籍上存储附魔时使用的最大等级。
                "max": 3
            },
            // 可供书籍选择的可用附魔列表。
            "options": [
                "minecraft:efficiency"
            ]
        },
        {
            // 确保附魔已成功添加且具有给定等级。
            "function": "minecraft:filtered",
            "item_filter": {
                "items": "minecraft:enchanted_book",
                "predicates": {
                    "minecraft:stored_enchantments": [
                        {
                            "levels": {
                                // 选择书籍上存储附魔时使用的最小等级。
                                "min": 3,
                                // 选择书籍上存储附魔时使用的最大等级。
                                "max": 3
                            }
                        }
                    ]
                }
            },
            // 失败时丢弃
            "on_fail": {
                "function": "minecraft:discard"
            }
        }
    ],
    // 商人给予附魔书。
    "gives": {
        "count": 1,
        "id": "minecraft:enchanted_book"
    },
    // 补货前可以进行的最大交易次数被硬编码为 12。
    "max_uses": 12,
    // 应用于报价的价格乘数,考虑声誉和需求,硬编码为 0.2。
    "reputation_discount": 0.2,
    "wants": {
        "count": {
            "type": "minecraft:sum",
            "summands": [
                // 基于附魔最小和最大等级的硬编码计算。
                11.0,
                {
                    "type": "minecraft:uniform",
                    "max": 35.0,
                    "min": 0.0
                }
            ]
        },
        "id": "minecraft:emerald"
    },
    // 交易给予的经验值。
    "xp": 30
}

// 对于某个村民交易 'examplemod:emerald_to_enchanted_item'
// JSON 位于 'data/examplemod/villager_trade/emerald_to_enchanted_item.json'
{
    "given_item_modifiers": [
        {
            // 将附魔应用于给定的装备。
            "function": "minecraft:enchant_with_levels",
            "include_additional_cost_component": true,
            "levels": {
                "type": "minecraft:uniform",
                "max": 20,
                "min": 5
            },
            "options": "#minecraft:on_traded_equipment"
        },
        {
            // 检查以确保附魔已应用。
            "function": "minecraft:filtered",
            "item_filter": {
                "items": "minecraft:fishing_rod",
                "predicates": {
                    "minecraft:enchantments": [
                        {}
                    ]
                }
            },
            // 失败时,不给予任何东西。
            "on_fail": {
                "function": "minecraft:discard"
            }
        }
    ],
    "gives": {
        "count": 1,
        // 商人将给予并尝试附魔的物品。
        "id": "minecraft:fishing_rod"
    },
    // 补货前可以进行的最大交易次数。
    "max_uses": 3,
    // 应用于报价的价格乘数,考虑声誉和需求。
    "reputation_discount": 0.2,
    "wants": {
        "count": {
            "type": "minecraft:sum",
            "summands": [
                // 商人想要的绿宝石基础数量。
                3,
                {
                    // 基于附魔等级的变化。
                    // 最初,这将是物品函数中使用的值,但由于它们现在被隔离,
                    // 这些值可能不同。
                    "type": "minecraft:uniform",
                    "max": 20,
                    "min": 5
                }
            ]
        },
        "id": "minecraft:emerald"
    },
    // 交易给予的经验值。
    "xp": 10
}

物品和绿宝石 -> 药水效果物品

对于以下交易:

public static final VillagerTrades.ItemListing EMERALD_TO_SUSPICIOUS_STEW = new VillagerTrades.SuspiciousStewForEmerald(
    // 可疑炖菜应用的效果。
    MobEffects.NIGHT_VISION,
    // 效果应激活的刻数。
    100,
    // 交易给予的经验值。
    15
);

public static final VillagerTrades.ItemListing ITEM_EMERALD_TO_TIPPED_ARROW = new VillagerTrades.TippedArrowForItemsAndEmeralds(
    // 商人额外想要的物品。
    Items.ARROW,
    // 商人额外想要的物品数量。
    5,
    // 商人将给予的物品。
    Items.TIPPED_ARROW,
    // 商人将给予的物品数量。
    5,
    // 商人想要的绿宝石数量。
    2,
    // 补货前可以进行的最大交易次数。
    12,
    // 交易给予的经验值。
    30
);

等价形式为:

// 对于某个村民交易 'examplemod:emerald_to_suspicious_stew'
// JSON 位于 'data/examplemod/villager_trade/emerald_to_suspicious_stew.json'
{
    "given_item_modifiers": [
        {
            "effects": [
                {
                    // 可疑炖菜应用的效果。
                    "type": "minecraft:night_vision",
                    // 效果应激活的刻数。
                    "duration": 100
                }
                // 原版将所有可疑炖菜报价合并为一个,
                // 因为此函数随机选择一个炖菜效果。
            ],
            "function": "minecraft:set_stew_effect"
        }
    ],
    "gives": {
        "count": 1,
        "id": "minecraft:suspicious_stew"
    },
    // 补货前可以进行的最大交易次数,硬编码为 12。
    "max_uses": 12,
    // 应用于报价的价格乘数,考虑声誉和需求,硬编码为 0.05。
    "reputation_discount": 0.05,
    "wants": {
        "id": "minecraft:emerald"
    },
    // 交易给予的经验值。
    "xp": 15
}

// 对于某个村民交易 'examplemod:item_emerald_to_tipped_arrow'
// JSON 位于 'data/examplemod/villager_trade/item_emerald_to_tipped_arrow.json'
{
    "additional_wants": {
        // 商人额外想要的物品数量。
        "count": 5,
        // 商人额外想要的物品。
        "id": "minecraft:arrow"
    },
    "given_item_modifiers": [
        {
            // 从可交易的药水中随机应用一种药水效果。
            // 原始实现只是随机选择任何药水。
            "function": "minecraft:set_random_potion",
            "options": "#minecraft:tradeable"
        }
    ],
    "gives": {
        // 商人将给予的物品数量。
        "count": 5,
        // 商人将给予的物品。
        "id": "minecraft:tipped_arrow"
    },
    // 补货前可以进行的最大交易次数。
    "max_uses": 12,
    // 应用于报价的价格乘数,考虑声誉和需求,硬编码为 0.05。
    "reputation_discount": 0.05,
    "wants": {
        // 商人想要的绿宝石数量。
        "count": 2,
        "id": "minecraft:emerald"
    },
    // 交易给予的经验值。
    "xp": 30
}

绿宝石 -> 宝藏地图

对于以下交易:

public static final VillagerTrades.ItemListing EMERALD_TO_TREASURE_MAP = new VillagerTrades.TreasureMapForEmeralds(
    // 商人想要的绿宝石数量。
    8,
    // 一个包含要找到最近宝藏结构的列表的标签。
    StructureTags.ON_TAIGA_VILLAGE_MAPS,
    // 地图名称的翻译键。
    "filled_map.village_taiga",
    // 用于装饰地图上找到的宝藏位置的图标。
    MapDecorationTypes.TAIGA_VILLAGE,
    // 补货前可以进行的最大交易次数。
    12,
    // 交易给予的经验值。
    5
);

等价形式为:

// 对于某个村民交易 'examplemod:emerald_to_treasure_map'
// JSON 位于 'data/examplemod/villager_trade/emerald_to_treasure_map.json'
{
    "additional_wants": {
        // 商人额外想要的物品,硬编码为指南针。
        "id": "minecraft:compass"
    },
    "given_item_modifiers": [
        {
            // 找到要在地图上显示的宝藏结构。

            // 用于装饰地图上找到的宝藏位置的图标。
            "decoration": "minecraft:village_taiga",
            // 一个包含要找到最近宝藏结构的列表的标签。
            "destination": "minecraft:on_taiga_village_maps",
            "function": "minecraft:exploration_map",
            "search_radius": 100
        },
        {
            // 设置地图的名称。

            "function": "minecraft:set_name",
            "name": {
                // 地图名称的翻译键。
                "translate": "filled_map.village_taiga"
            },
            "target": "item_name"
        },
        {
            // 检查以确保找到了结构。

            "function": "minecraft:filtered",
            "item_filter": {
                "items": "minecraft:filled_map",
                "predicates": {
                    "minecraft:map_id": {}
                }
            },
            "on_fail": {
                "function": "minecraft:discard"
            }
        }
    ],
    "gives": {
        "count": 1,
        // 返回一张填充了宝藏位置的地图。
        "id": "minecraft:map"
    },
    // 补货前可以进行的最大交易次数。
    "max_uses": 12,
    // 应用于报价的价格乘数,考虑声誉和需求,硬编码为 0.05。
    "reputation_discount": 0.05,
    "wants": {
        // 商人想要的绿宝石数量。
        "count": 8,
        "id": "minecraft:emerald"
    },
    // 交易给予的经验值。
    "xp": 5
}

村民变体

一些商人会根据村民类型提供不同的选项,作为一个巨大的物品列表映射。现在,每种类型都有自己独立的村民交易,使用 merchant_predicate 来检查是否可以向特定村民类型提供报价:

// 对于某个村民交易 'examplemod:villager_type_item'
// JSON 位于 'data/examplemod/villager_trade/villager_type_item.json'
{
    // ...
    "merchant_predicate": {
        // 检查实体。
        "condition": "minecraft:entity_properties",
        "entity": "this",
        "predicate": {
            "predicates": {
                // 村民类型必须是沙漠才能选择此交易。
                "minecraft:villager/variant": "minecraft:desert"
            }
        }
    },
    // ...
}
  • net.minecraft.core.registries.Registries
    • TRADE_SET - 指向持有交易列表的注册表的键。
    • VILLAGER_TRADE - 指向持有单个交易的注册表的键。
  • net.minecraft.tags.VillagerTradeTags - 村民交易的标签。
  • net.minecraft.world.entity.npc.villager
    • AbstractVillager#addOffersFromItemListings -> addOffersFromTradeSet,接受交易集的键而不是 $ItemListing 和报价数量;不是一对一
    • VillagerProfession 现在接受一个交易员等级到 TradeSet 的映射
      • getTrades - 返回给定等级的交易集键。
    • VillagerTrades 已被拆分为许多不同的类和实现
      • TRADESEXPERIMENTAL_TRADESWANDERING_TRADER_TRADES 现在由 VillagerProfession#tradeSetsByLevel 表示
        • 由于它们现在是数据包条目,因此存储在其各自的数据包中
        • TRADESEXPERIMENTAL_TRADESdata/minecraft/trade_set/<profession>/* 表示
        • WANDERING_TRADER_TRADESdata/minecraft/trade_set/wandering_trader/* 表示
      • $DyedArmorForEmeralds -> VillagerTrades#dyedItemaddRandomDye;不是一对一
      • $EmeraldForItems -> VillagerTrade,不是一对一
      • $EmeraldsForVillagerTypeItem -> VillagerTrades#registerBoatTrades,参见用法,不是一对一
      • $EnchantBookForEmeralds -> VillagerTrades#enchantedBook,不是一对一
      • $EnchantedItemForEmeralds -> VillagerTrades#enchantedItem,不是一对一
      • $ItemListing -> VillagerTrade
      • $ItemsAndEmeraldsToItems -> 带有 additionalWantsVillagerTrade
      • $ItemsForEmeralds -> VillagerTrade,不是一对一
      • $SuspiciousStewForEmerald -> 带有 SetStewEffectFunctionVillagerTrade
      • $TippedArrowForItemsAndEmeralds -> 带有 SetRandomPotionFunctionVillagerTrade
      • $TreasureMapForEmeralds -> VillagerTrades$VillagerExplorerMapEntry,参见用法,不是一对一
      • $TypeSpecificTrade -> VillagerTrades#villagerTypeRestrictionvillagerTypeHolderSet;不是一对一
  • net.minecraft.world.item.enchantment.providers.TradeRebalanceEnchantmentProviders 接口已移除
    • TradeRebalanceVillagerTradesTradeRebalanceRegistries 取代
  • net.minecraft.world.item.trading
    • TradeCost - 正在与某个商人交易的 ItemStack
    • TradeRebalanceVillagerTrades - 属于交易平衡数据包的所有交易。
    • TradeSet - 一组可以由某个等级的交易员执行的交易。
    • TradeSets - 某个等级的交易员的所有原版交易集。
    • VillagerTrade - 商人和玩家之间的交易。
    • VillagerTrades - 所有原版交易。
  • net.minecraft.world.level.storage.loot.parameters.LootContextParamSets#VILLAGER_TRADE - 进行村民交易时的战利品上下文,包含交易来源和交易实体。

Level#random 字段现在为 protected

Level#random 字段现在是 protected 而不是 public。因此,应改用公共的 getRandom 方法。

// 对于某个 Level level
RandomSource random = level.getRandom();
  • net.minecraft.world.level.Level#random 字段现在是 protected 而不是 public
    • 改用 getRandom 方法

数据组件初始化器

数据组件已开始从原始对象转移到 Holder 本身。这是为了正确处理在构造期间不可用的对象,例如物品的数据包注册表对象。目前,这仅针对 Item 实现,但该系统允许任何注册表对象(给定其包装的持有者)存储某些定义的数据组件。

数据组件通过 DataComponentInitializers 附加到其持有者。在对象构造期间,调用 DataComponentInitializers#add,提供注册表对象的 ResourceKey 标识符以及一个 DataComponentInitializers$Initializer。初始化器接受三个参数:组件映射的构建器、完整的注册表 HolderLookup$Provider 以及传递给 DataComponentInitializers#add 的键。初始化器的功能类似于消费者,也允许通过 $Initializer#andThen 链接其他初始化器,或通过 $Initializer#add 轻松添加组件。

// 对于某个自定义注册表对象
public ExampleObject(ResourceKey<ExampleObject> id) {
    // 注册数据组件初始化器
    BuiltInRegistries.DATA_COMPONENT_INITIALIZERS.add(
        // 注册表对象的标识符
        id,
        // 初始化器函数,接受组件构建器、注册表上下文和 id
        (components, context, key) -> components
            .set(DataComponents.MAX_DAMAGE, 1)
            .set(DataComponents.DAMAGE_TYPE, context.getOrThrow(DamageTypes.SPEAR))
    );
}

然后,每当调用 ReloadableServerResources#loadResources(在数据包重载时)时,数据组件就会被初始化或重新初始化。首先加载数据包对象,然后在 Holder$Reference 上设置组件。然后,可以通过 Holder#components 收集组件。

// 对于某个 Holder<ExampleObject> EXAMPLE_HOLDER
DataComponentMap components = EXAMPLE_HOLDER.components();

物品

由于组件现在在资源重载期间初始化,Item$Properties 提供了两种方法来将组件初始化延迟到此类数据组件加载完成之后:delayedComponentdelayedHolderComponentdelayedComponent 接受组件类型和一个接受 HolderLookup$Provider 并返回组件值的函数。delayedHolderComponent 委托给 delayedComponent,接受一个 ResourceKey 并将注册表对象设置为组件值。

public static final Item EXAMPLE_ITEM = new Item(
    new Item.Properties()
        .delayedComponent(
            // 应延迟初始化的组件类型。
            DataComponents.JUKEBOX_PLAYABLE,
            // 一个接受注册表并返回组件值的函数。
            context -> new JukeboxPlayable(context.getOrThrow(
                JukeboxSongs.THIRTEEN
            ))
        )
        .delayedHolderComponent(
            // 具有持有者值类型的组件类型。
            DataComponents.DAMAGE_TYPE
            // 关联持有者泛型类型的注册表对象的资源键。
            DamageTypes.SPEAR
        )
        // ...
);

配方

由于数据组件现在持有在资源重载后延迟初始化的真实值,Recipe#assemble 不再接受 HolderLookup$Provider。相反,它假设配方已将所有必需的数据存储在传递到配方的堆栈或直接存储中。

  • net.minecraft.core
    • Holder
      • areComponentsBound - 组件是否已绑定到持有者。
      • components - 存储在持有者上的对象组件。
      • direct$Direct 现在可以接受 DataComponentMap
      • $Reference#bindComponents - 将组件存储在持有者引用上。
    • Registry#componentLookup - 获取组件到持有者的查找。
    • WritableRegistry#bindTag -> bindTags,现在接受一个键到持有者列表的映射,而不是一个映射
  • net.minecraft.core.component
    • DataComponentInitializers - 一个处理为组件附加对象初始化数据组件的类。
    • DataComponentLookup - 一个将组件类型映射到使用它的持有者的查找表。
    • DataComponentMap$Builder#addValidator - 为对象上的组件添加验证器。
    • DataComponentPatch
      • get 现在接受 DataComponentGetter 并返回原始组件值
      • $Builder#set 现在有一个接受 TypedDataComponent 可迭代对象的重载
    • DataComponents
      • DAMAGE_TYPE 现在是一个持有者包装的 DamageType,而不是 EitherHolder 包装的
      • PROVIDES_TRIM_MATERIAL 现在是一个持有者包装的 TrimMaterial,而不是 ProvidesTrimMaterial
      • CHICKEN_VARIANT 现在是一个持有者包装的 ChickenVariant,而不是 EitherHolder 包装的
      • ZOMBIE_NAUTILUS_VARIANT 现在是一个持有者包装的 ZombieNautilusVariant,而不是 EitherHolder 包装的
      • PROVIDES_BANNER_PATTERNS 现在是一个 HolderSet,而不是 TagKey
  • net.minecraft.core.registries
    • BuiltInRegistries#DATA_COMPONENT_INITIALIZERS - 附加到注册表条目的数据组件列表。
    • Registries#componentsDirPath - 注册表中组件的路径目录。
  • net.minecraft.data.PackOutput#createRegistryComponentPathProvider - 用于组件注册表报告的路径提供者。
  • net.minecraft.data.info.ItemListReport -> RegistryComponentsReport,不是一对一
  • net.minecraft.resources
    • NetworkRegistryLoadTask - 一个加载任务,处理从网络注册注册表对象和标签,否则从资源注册。
    • RegistryDataLoader
      • $PendingRegistration -> RegistryLoadTask$PendingRegistration
      • $RegistryData 现在接受一个 RegistryValidator 而不是一个 boolean
      • $RegistryLoadTask -> RegistryLoadTask,不是一对一
    • RegistryValidator - 一个接口,用于验证注册表中的条目,将所有错误存储在映射中。
    • ResourceManagerRegistryLoadTask - 一个加载任务,处理从本地资源管理器注册注册表对象和标签。
  • net.minecraft.server.ReloadableServerResources#updateStaticRegistryTags -> updateComponentsAndStaticRegistryTags,不是一对一
  • net.minecraft.world.item
    • EitherHolder 类已移除
    • Item
      • CODEC_WITH_BOUND_COMPONENTS - 一个验证组件已绑定的物品编解码器。
      • $Properties
        • delayedComponent - 延迟设置组件,提供 HolderLookup$Provider 以获取任何动态元素。
        • delayedHolderComponent - 为某个持有者包装的注册表对象延迟设置组件。
    • ItemStack#validateComponents 现在从 public 变为 private
    • JukeboxPlayable 现在持有持有者包装的 JukeboxSong,而不是 EitherHolder 包装的变体
    • JukeboxSong#fromStack 不再接受 HolderLookup$Provider
    • SpawnEggItem
      • spawnEntity 现在是 static
      • byId 现在返回一个可选的持有者包装的 Item,而不是 SpawnEggItem
      • eggs 已移除
      • getType 现在是 static
      • spawnOffspringFromSpawnEgg 现在是 static
  • net.minecraft.world.item.component
    • BlocksAttacks 现在持有一个可选的持有者集包装的 DamageType,而不是 TagKey
    • DamageResistant 现在持有一个持有者集 DamageType,而不是 TagKey
    • InstrumentComponent 现在持有一个持有者包装的 Instrument,而不是 EitherHolder 包装的变体
      • unwrap 已移除
    • ProvidesTrimMaterial 现在持有一个持有者包装的 TrimMaterial,而不是 EitherHolder 包装的变体
  • net.minecraft.world.item.crafting
    • Recipe#assemble 不再接受 HolderLookup$Provider
    • SmithingTrimRecipe#applyTrim 不再接受 HolderLookup$Provider
  • net.minecraft.world.item.equipment.trim.TrimMaterials#getFromIngredient 已移除
  • net.minecraft.world.level.storage.loot.functions.SetInstrumentFunction#setInstrumentOptions 现在接受持有者集包装的 Instrument,而不是 TagKey
  • net.minecraft.world.timeline.Timeline#validateRegistry - 验证每个时间标记仅定义一次。

物品实例与堆栈模板

ItemStack 现在有一个称为 ItemStackTemplate 的不可变实例。与 ItemStack 类似,它包含持有者包装的 Item、它表示的物品数量以及要应用于堆栈的组件的 DataComponentPatch。模板可以通过 create 转换为堆栈,或者如果需要添加额外数据组件,则通过 apply 转换。ItemStack 同样可以通过 ItemStackTemplate#fromNonEmptyStack 转换为模板。现在在需要不可变性的地方(例如,进度、配方等)使用模板代替 ItemStack。它们为网络通信提供了常规的 CODECMAP_CODECSTREAM_CODEC

ItemStackTemplate apple = new ItemStackTemplate(
    // 堆栈的物品
    Items.APPLE.builtInRegistryHolder(),
    // 持有的物品数量
    5,
    // 应用于堆栈的组件
    DataComponentPatch.builder()
        .set(DataComponents.ITEM_NAME, Component.literal("苹果?"))
        .build()
);

// 将模板转换为堆栈
ItemStack stack = apple.create();

// 从非空堆栈创建模板
ItemStackTemplate fromStack = ItemStackTemplate.fromNonEmptyStack(stack);

为了帮助标准化访问两者之间的通用组件,模板和堆栈都实现了 ItemInstance,它提供了对标准持有者方法检查、计数和 DataComponentGetter 的访问。公共接口还意味着,如果堆栈是否可变无关紧要,则可以使用 ItemInstance 作为类型。

// 两者都是物品实例
ItemInstance stack = new ItemStack(Items.APPLE);
ItemInstance template = new ItemStackTemplate(Items.APPLE);

// 获取持有者或检查某些内容
Holder<Item> item = stack.typeHolder();
template.is(Items.APPLE);

// 获取堆栈或模板中的物品数量
int stackCount = stack.count();
int templateCount = template.count();

// 获取组件值
Identifier stackModel = stack.get(DataComponents.ITEM_MODEL);
Identifier templateModel = template.get(DataComponents.ITEM_MODEL);

配方构建器

由于 ItemStackTemplate 的加入,RecipeBuilder 的实现略有变化。首先,构建器不再为结果存储 Item,而是将 defaultId 定义为配方的资源键。因此,这允许更清晰地定义不导出 Item 的自定义配方。

当然,这种新格式的更改只需让 defaultId 返回带有 ItemInstance(堆栈或模板)的 RecipeBuilder#getDefaultRecipeId,如下所示:

public class ExampleRecipeBuilder implements RecipeBuilder {

    // 配方的结果
    private final ItemStackTemplate result;

    public ExampleRecipeBuilder(ItemStackTemplate result) {
        this.result = result;
    }

    @Override
    public ResourceKey<Recipe<?>> defaultId() {
        // 从结果获取默认配方 id
        return RecipeBuilder.getDefaultRecipeId(this.result);
    }

    // 在此处实现其他所有内容
    // ...
}
  • net.minecraft.advancements
    • Advancement$Builder#display 现在接受 ItemStackTemplate 而不是 ItemStack
    • DisplayInfo 现在接受 ItemStackTemplate 而不是 ItemStack
      • getIcon 现在返回 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.advancements.criterion
    • AnyBlockInteractionTrigger#trigger 现在接受 ItemInstance 而不是 ItemStack
    • ItemPredicate 现在实现 ItemInstance 的谓词而不是 ItemStack
    • ItemUsedOnLocationTrigger#trigger 现在接受 ItemInstance 而不是 ItemStack
  • net.minecraft.client.particle.BreakingItemParticle$ItemParticleProvider#getSprite 现在接受 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.commands.arguments.item
    • ItemInput 现在是一个记录
      • serialize 已移除
      • createItemStack 不再接受用于检查大小的 boolean
    • ItemParser#parse 现在返回 ItemResult 而不是 ItemParser$ItemResult
      • $ItemResult 合并到 ItemInput
  • net.minecraft.core.component.predicates
    • BundlePredicate 现在处理 ItemInstance 的可迭代对象而不是 ItemStack
    • ContainerPredicate 现在处理 ItemInstance 的可迭代对象而不是 ItemStack
  • net.minecraft.core.particles.ItemParticleOption 现在接受 ItemStackTemplate 而不是 ItemStack
    • 还有一个接受常规 Item 的重载
    • getItem 现在返回 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.data.recipes
    • RecipeBuilder
      • getResult 已移除
      • defaultId - 使用此构建器制作的配方的默认标识符。
      • getDefaultRecipeId 现在接受 ItemInstance 而不是 ItemLike
    • RecipeProvider
      • oreSmeltingoreBlasting 现在接受 CookingBookCategory
      • oreCooking 不再接受 RecipeSerializer,现在接受 CookingBookCategory
      • cookRecipessimpleCookingRecipe 不再接受 RecipeSerializer
      • shapeless 现在接受 ItemStackTemplate 而不是 ItemStack
    • ShapedRecipeBuilder 现在接受 ItemStackTemplate 作为结果,ItemLike 移至重载
      • 两个构造函数都是 private
    • ShapelessRecipeBuilder 现在接受 ItemStackTemplate 作为结果而不是 ItemStack
    • SimpleCookingRecipeBuilder 现在接受 ItemStackTemplate 作为结果,ItemLike 移至重载
      • generic 不再接受 RecipeSerializer,现在接受 CookingBookCategory
      • blastingsmelting 现在接受 CookingBookCategory
    • SingleItemRecipeBuilder 现在接受 ItemStackTemplate 作为结果,ItemLike 移至重载
      • ItemStackTemplate 构造函数是 private
    • SmithingTransformRecipeBuilder 现在接受 ItemStackTemplate 作为结果而不是 Item
    • TransmuteRecipeBuilder 现在接受 ItemStackTemplate 作为结果而不是 Holder<Item>
      • 构造函数是 private
      • transmute 现在有一个接受 ItemStackTemplate 作为结果的重载
      • addMaterialCountToOutputsetMaterialCount - 根据使用的材料数量处理结果堆栈的大小。
  • net.minecraft.network.chat.HoverEvent$ShowItem 现在接受 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.server.dialog.body.ItemBody 现在接受 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.world.entity.LivingEntity
    • dropFromEntityInteractLootTable 现在接受 ItemInstance 而不是 ItemStack 作为工具
    • dropFromShearingLootTable 现在接受 ItemInstance 而不是 ItemStack 作为工具
  • net.minecraft.world.item
    • BundleItem#getSelectedItemStack -> getSelectedItem,现在返回 ItemStackTemplate 而不是 ItemStack
    • Item
      • getCraftingRemainder 现在返回 ItemStackTemplate 而不是 ItemStack
      • $Properties#craftRemainder 现在有一个接受 ItemStackTemplate 的重载
    • ItemInstance - 一个类型化的物品实例,可以查询物品、大小及其组件。
    • ItemStack 现在实现 ItemInstance
      • SINGLE_ITEM_CODECSTRICT_CODECSTRING_SINGLE_ITEM_CODECSIMPLE_ITEM_CODEC 已移除
      • getMaxStackSize -> ItemInstance#getMaxStackSize
    • ItemStackTemplate - 一个包含堆栈不可变组件的记录:物品、数量和组件。
  • net.minecraft.world.item.component
    • BundleContents 现在接受 ItemStackTemplate 列表而不是 ItemStack
      • items 现在返回 ItemStackTemplate 列表而不是 ItemStack 的可迭代对象
      • itemsCopy 已移除
      • getSelectedItem - 返回选中物品的堆栈模板,如果没有选中物品则返回 null
    • ChargedProjectile 现在是一个记录
      • 构造函数接受 ItemStackTemplate 列表而不是 ItemStack
      • of -> ofNonEmpty
      • getItems -> itemCopies
    • ItemContainerContents
      • stream -> allItemsCopyStream
      • nonEmptyStream -> nonEmptyItemCopyStream
      • nonEmptyItemsnonEmptyItemsCopy -> nonEmptyItems,现在返回 ItemStackTemplate 的可迭代对象而不是 ItemStack
    • UseRemainder 现在接受 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.world.item.crafting
    • AbstractCookingRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
      • $Factory#create 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • BlastingRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • CampfireCookingRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • ShapedRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • ShapelessRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • SingleItemRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
      • result 现在返回 ItemStackTemplate 而不是 ItemStack
      • $Factory#create 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • SmeltingRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • SmithingTransformRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • SmokingRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • StonecutterRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • TransmuteRecipe 现在接受 ItemStackTemplate 而不是 ItemStack 作为结果
    • TransmuteResult -> ItemStackTemplate,不是一对一
      • isResultUnchanged 已移除
      • apply -> TransmuteRecipe#createWithOriginalComponents,不是一对一
  • net.minecraft.world.item.crafting.display.SlotDisplay$ItemStackSlotDisplay 现在接受 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.world.item.enchantment.EnchantmentHelper#getItemEnchantmentLevel 现在接受 ItemInstance 而不是 ItemStack
  • net.minecraft.world.level.block.Block
    • dropFromBlockInteractLootTable 现在接受 ItemInstance 而不是 ItemStack
    • getDrops 现在接受 ItemInstance 而不是 ItemStack
  • net.minecraft.world.level.block.entity.DecoratedPotBlockEntity#createdDecoratedPotItem -> createdDecoratedPotInstance
    • createDecoratedPotTemplate 创建 ItemStackTemplate 而不是 ItemStack
  • net.minecraft.world.level.storage.loot
    • LootContext$ItemStackTarget 现在为参数获取器实现 ItemInstance 泛型,而不是 ItemStack
    • LootContextArg$ArgCodecBuilder#anyItemStack 现在需要一个接受 ItemInstance 上下文键的函数,而不是 ItemStack 上下文键
  • net.minecraft.world.level.storage.loot.parameters.LootContextParams#TOOL 现在是 ItemInstance 上下文键,而不是 ItemStack 上下文键

序列化器记录与配方信息

配方的实现已略有重做。首先,RecipeSerializer 现在是一个记录,接受用于序列化和反序列化配方的 MapCodecStreamCodec。因此,Serializer 类已被完全移除,取而代之的是在注册期间向记录提供编解码器:

// 假设某个 ExampleRecipe 实现了 Recipe
// 我们假设只有一个 INSTANCE
public static final RecipeSerializer<ExampleRecipe> EXAMPLE_RECIPE = new RecipeSerializer<>(
    // 用于从磁盘读取/写入配方的映射编解码器。
    MapCodec.unit(INSTANCE),
    // 用于从网络读取/写入配方的流编解码器。
    StreamCodec.unit(INSTANCE)
);

其次,一些关于配方设置和配方书信息的常见数据已被分离到单独的对象中。这些对象作为构造函数的一部分传递给配方,并用于更清晰地处理所有配方的类似实现。

原版提供了四个这样的常见对象类,分为两个不同的类别。Recipe$CommonInfo 用于通用配方设置。同时,Recipe$BookInfo 用于配方书信息,CraftingRecipe$CraftingBookInfo 用于合成配方,以及 AbstractCookingRecipe$CookingBookInfo 用于烹饪配方(例如,熔炼、高炉等)。这些常见对象类提供了根据需要构造编解码器的方法,然后可以将其传递给相关的配方编解码器。

这些类通常通过 Recipe 子类传递,用作实现抽象方法的样板。这些对象中的数据都不能直接在实现本身之外访问,只能通过 Recipe 接口中定义的方法访问。因此,可以使用 NormalCraftingRecipeCustomRecipeSimpleSmithingRecipeSingleItemRecipeAbstractCookingRecipe 等类通过实现几个方法来创建新的配方实现。

请注意,这些常见信息类是一种设计理念,您可以根据需要选择实现。只有在构建现有配方子类型时才需要使用它们。

  • net.minecraft.data.recipes
    • CustomCraftingRecipeBuilder - 一个配方构建器,从某些常见和合成书籍信息创建任意合成配方。
    • RecipeBuilder
      • determineBookCategory -> determineCraftingBookCategory
      • createCraftingCommonInfo - 创建常见的配方信息。
      • createCraftingBookInfo - 创建合成书籍信息。
    • RecipeUnlockAdvancementBuilder - 用于解锁配方的进度构建器。
    • SpecialRecipeBuilderspecial 现在接受一个提供的 Recipe 而不是一个 CraftingBookCategoryRecipe 的函数
      • unlockedBy - 解锁配方进度所需的条件。
  • net.minecraft.world.item.crafting
    • AbstractCookingRecipe 现在接受 Recipe$CommonInfo$CookingBookInfo 而不是 group 和 CookingBookCategory
      • $Factory#create 现在接受 Recipe$CommonInfo$CookingBookInfo 而不是 group 和 CookingBookCategory
      • $SerializercookingMapCodeccookingStreamCodec 取代
      • $CookingBookInfo - 一个包含配方书常见烹饪信息的记录。
    • BannerDuplicateRecipe 现在接受旗帜 IngredientItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • BlastingRecipe 现在接受 Recipe$CommonInfo$AbstractCookingRecipeCookingBookInfo 而不是 group 和 CookingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • BookCloningRecipe 现在接受源和材料的 Ingredient、定义可复制代数的 MinMaxBounds$Ints,以及 ItemStackTemplate 结果,而不是 CraftingBookCategory
      • ALLOWED_BOOK_GENERATION_RANGESDEFAULT_BOOK_GENERATION_RANGES - 书籍代数克隆的范围。
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • CampfireCookingRecipe 现在接受 Recipe$CommonInfoAbstractCookingRecipe$CookingBookInfo 而不是 group 和 CookingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • CraftingRecipe$CraftingBookInfo - 一个包含配方书常见合成信息的记录。
    • CustomRecipe 不再接受任何构造函数参数
      • $Serializer 已移除,被其实现的编解码器取代
    • DecoratedPotRecipe 现在接受每侧的 Ingredient 图案以及 ItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • DyeRecipe 现在接受 Recipe$CommonInfoCraftingRecipe$CraftingBookInfo,以及目标物品和染料的 IngredientItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • FireworkRocketRecipe 现在接受外壳、燃料和星星的 Ingredient 以及 ItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • FireworkStarFadeRecipe 现在接受目标物品和染料的 Ingredient 以及 ItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • FireworkStarRecipe 现在接受 $ShapeIngredient 的映射;踪迹、闪烁、燃料和染料的 Ingredient;以及 ItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • MapCloningRecipeTransmuteRecipe 取代
    • MapExtendingRecipe 现在扩展 CustomRecipe 而不是 ShapedRecipe
      • 构造函数现在接受地图和材料的 Ingredient 以及 ItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • NormalCraftingRecipe - 一个定义合成配方标准实现的类。
    • Recipe
      • showNotificationgroup 不再是默认的
      • $BookInfo - 配方书的信息。
      • $CommonInfo - 所有配方的常见信息。
    • RecipeSerializer 现在是一个包含 MapCodecStreamCodec 的记录
      • 注册的条目已移至 RecipeSerializers
      • register 已移除
    • RecipeSerializers - 所有配方的原版序列化器。
    • RepairItemRecipe 不再接受任何参数
      • INSTANCE - 配方序列化器单例。
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • ShapedRecipe 现在扩展 NormalCraftingRecipe 而不是实现 CraftingRecipe
      • 构造函数现在接受 Recipe$CommonInfoCraftingRecipe$CraftingBookInfo 而不是 group 和 CraftingBookCategory
      • $Serializer -> MAP_CODECSTREAM_CODECSERIALIZER;不是一对一
    • ShapelessRecipe 现在扩展 NormalCraftingRecipe 而不是实现 CraftingRecipe
      • 构造函数现在接受 Recipe$CommonInfoCraftingRecipe$CraftingBookInfo 而不是 group 和 CraftingBookCategory
      • $Serializer -> MAP_CODECSTREAM_CODECSERIALIZER;不是一对一
    • ShieldDecorationRecipe 现在接受旗帜和目标物品的 Ingredient 以及 ItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • SimpleSmithingRecipe - 一个定义锻造配方标准实现的类。
    • SingleItemRecipe 现在接受 Recipe$CommonInfo 而不是 group
      • commonInfo - 配方的常见信息。
      • $Factory#create 现在接受 Recipe$CommonInfo 而不是 group
      • $Serializer -> simpleMapCodecsimpleStreamCodec;不是一对一
    • SmeltingRecipe 现在接受 Recipe$CommonInfoAbstractCookingRecipe$CookingBookInfo 而不是 group 和 CookingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • SmithingTransformRecipe 现在扩展 SimpleSmithingRecipe 而不是实现 SmithingRecipe
      • 构造函数现在接受 Recipe$CommonInfo
      • $Serializer -> MAP_CODECSTREAM_CODECSERIALIZER;不是一对一
    • SmithingTrimRecipe 现在扩展 SimpleSmithingRecipe 而不是实现 SmithingRecipe
      • 构造函数现在接受 Recipe$CommonInfo
      • $Serializer -> MAP_CODECSTREAM_CODECSERIALIZER;不是一对一
    • SmokingRecipe 现在接受 Recipe$CommonInfoAbstractCookingRecipe$CookingBookInfo 而不是 group 和 CookingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • StonecutterRecipe 现在接受 Recipe$CommonInfo 而不是 group
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • TippedArrowRecipe -> ImbueRecipe,不是一对一
      • 构造函数现在接受 Recipe$CommonInfoCraftingRecipe$CraftingBookInfo,以及源材料和材料的 IngredientItemStackTemplate 结果,而不是 CraftingBookCategory
      • MAP_CODECSTREAM_CODECSERIALIZER - 配方的序列化器。
    • TransmuteRecipe 现在扩展 NormalCraftingRecipe 而不是实现 CraftingRecipe
      • 构造函数现在接受 Recipe$CommonInfoCraftingRecipe$CraftingBookInfo,以及处理材料数量并将其添加到结果的 MinMaxBounds$Intsboolean,而不是 group 和 CraftingBookCategory
      • $Serializer -> MAP_CODECSTREAM_CODECSERIALIZER;不是一对一
  • net.minecraft.world.item.crafting.display.SlotDisplay
    • $OnlyWithComponent - 仅当内容具有所需组件时才显示的显示。
    • $WithAnyPotion - 内容具有任何药水内容组件的显示。
  • net.minecraft.world.level.storage.loot.functions.SmeltItemFunction#smelted 现在可以接受是否使用输入材料数量

染料组件

指定物品是否可用作染料材料现在通过 DYE 数据组件处理。该组件指定一个 DyeColor,可以通过 Item$Properties#component 设置:

public static final Item EXAMPLE_DYE = new Item(new Item.Properties().component(
    DataComponents.DYE, DyeColor.WHITE
));

然而,染料材料的行为并不仅仅由组件本身完全涵盖。在大多数情况下,该组件与某些其他标签或子类结合使用以获得所需的行为。

实体和告示牌

给绵羊和告示牌染色完全通过 DyeItem 子类处理,检查物品是否具有 DYE 组件。

另一方面,给狼和猫的项圈染色可以是任何物品,只要它具有 DYE 组件即可。此外,该物品必须分别位于 ItemTags#WOLF_COLLAR_DYESItemTags#CAT_COLLAR_DYES 标签中。

染料配方

DyeRecipe(以前称为 ArmorDyeRecipe)可以接受任何目标原料,并应用染料原料的颜色以获得带有关联 DYED_COLOR 组件的所需结果。任何物品都可以被视为染料;但是,没有 DYE 组件的物品将默认为 DyeColor#WHITE。盔甲使用 RecipeProvider#dyedItem 来允许 ItemTags#DYES 标签中的任何物品给盔甲染色。然而,捆绑包和潜影盒的颜色组件是不同的物品,这意味着默认配方直接与原版 DyeItem 绑定,因此需要为将这些物品应用染料生成单独的配方。

另一方面,织布机、烟花星和烟花星面配方期望任何染料材料都具有 DYE 组件。织布机还有一个额外要求,即物品位于 ItemTags#LOOM_DYES 标签中。

  • net.minecraft.core.component.DataComponents#DYE - 表示物品可以作为特定颜色的染料。
  • net.minecraft.data.recipes.RecipeProvider
    • dyedItem - 创建一个染色物品配方。
    • dyedShulkerBoxRecipe - 创建一个染色潜影盒配方。
    • dyedBundleRecipe - 创建一个染色捆绑包配方。
  • net.minecraft.world.item
    • BundleItem
      • getAllBundleItemColorsgetByColor 已移除
    • DyeColor#VALUES - 所有染料颜色的列表。
    • DyeItem 不再接受 DyeColor
      • getDyeColorbyColor 已移除
  • net.minecraft.world.item.component.DyedItemColor#applyDyes 现在接受 DyeColor 列表而不是 DyeItem
    • 还有一个重载可以接受 DyedItemColor 组件而不是 ItemStack
  • net.minecraft.world.item.crafting.ArmorDyeRecipe -> DyeRecipe,不是一对一
  • net.minecraft.world.item.crafting.display.SlotDisplay$DyedSlotDemo - 用于演示物品染色的显示。
  • net.minecraft.world.level.block
    • BannerBlock#byColor 已移除
    • ShulkerBoxBlock#getBlockByColorgetColoredItemStack 已移除

世界时钟与时间标记

世界时钟是表示从世界首次加载起每刻增加的时间的对象。这些时钟用作计时器,以正确处理基于时间的事件(例如,当前日期、睡眠)。原版提供了两个世界时钟:一个用于 minecraft:overworld,一个用于 minecraft:the_end

创建时钟非常简单:只需在 world_clock 中创建一个空的数据包注册表对象。

// 对于某个世界时钟 'examplemod:EXAMPLE_CLOCK'
// JSON 位于 'data/examplemod/world_clock/EXAMPLE_CLOCK.json'
{}

然后,您可以通过 ClockManager 通过 Level#clockManagerMinecraftServer#clockManager 查询时钟状态:

// 对于某个 Level level
// 假设我们有某个 ResourceKey<WorldClock> EXAMPLE_CLOCK

// 获取时钟引用
Holder.Reference<WorldClock> clock = level.registryAccess().getOrThrow(EXAMPLE_CLOCK);

// 查询时钟时间
long ticksPassed = level.clockManager().getTotalTicks(clock);

如果从服务器访问时钟,您还可以修改时钟的状态:

// 对于某个 ServerLevel level
// 假设我们有某个 ResourceKey<WorldClock> EXAMPLE_CLOCK

// 获取时钟引用
Holder.Reference<WorldClock> clock = level.registryAccess().getOrThrow(EXAMPLE_CLOCK);

// 获取服务器时钟管理器
ServerClockManager clockManager = level.clockManager();

// 设置已过去的刻数总数
clockManager.setTotalTicks(clock, 0L);

// 将刻数增加某个值
clockManager.addTicks(clock, 10L);

// 暂停时钟
clockManager.setPaused(
    clock,
    // `true` 暂停。
    // `false` 恢复。
    true
);

标记时间线

世界时钟本身的范围相当有限,因为您必须跟踪已过去的刻数。然而,当与时间线一起使用时,可以标记特定的重复时间来处理基于时间的事件。

作为回顾,Timeline 是一种基于某个 WorldClock 修改属性的方法。目前,所有原版时间线都使用 minecraft:overworld 世界时钟通过 clock 字段来跟踪它们的时间。所有时间线都必须定义它使用的时钟;但是,请注意,时钟默认不支持任何同步,这意味着更新一个时钟的时间不会影响另一个时钟。

// 对于某个时间线 'examplemod:example_timeline'
// 在 `data/examplemod/timeline/example_timeline.json
{
    // 使用自定义时钟。
    // 对时钟时间的任何更改只会影响
    // 使用此时钟的时间线。
    // 例如,`minecraft:overworld` 不会被更改。
    "clock": "examplemod:example_clock",
    // 以 24,000 刻的间隔执行操作。
    "period_ticks": "24000",
    // ...
}


// 对于某个时间线 'examplemod:example_timeline_2'
// 在 `data/examplemod/timeline/example_timeline_2.json
{
    // 使用与上面相同的时钟。
    // 对时钟时间的更改将影响这两个
    // 时间线。
    "clock": "examplemod:example_clock",
    // 以 1,000 刻的间隔执行操作。
    "period_ticks": "1000",
    // ...
}

// 对于某个时间线 'examplemod:example_overworld'
// 在 `data/examplemod/timeline/example_overworld.json
{
    // 使用原版主世界时钟。
    // 对时钟时间的更改不会影响
    // 上面的时间线,因为它们使用不同的
    // 时钟。
    "clock": "minecraft:overworld",
    // 以 6,000 刻的间隔执行操作。
    "period_ticks": "6000",
    // ...
}

时间线还可以定义时间标记,这只是世界时钟时间线周期内某个时间的标识符。这些通常用于命令内部(例如 /time set),以检查是否已经过了某个时间(例如,村庄袭击),或跳转到给定时间(例如,从睡眠中醒来)。时间标记在 time_markers 中定义,指定周期内的 ticks 以及是否可以在 show_in_commands 中显示。由于时间标记由其世界时钟标识,因此使用相同世界时钟的时间线不能定义相同的时间标记。

// 对于某个时间线 'examplemod:example_timeline'
// 在 `data/examplemod/timeline/example_timeline.json
{
    // 时钟的标识符。
    "clock": "examplemod:example_clock",
    // 以 24,000 刻的间隔执行操作。
    "period_ticks": "24000",
    // 时间线指定的周期内的标记
    "time_markers": {
        // 一个标记
        "examplemod:example_marker": {
            // 此标记表示的周期内的刻数。
            // 例如,5000、29000、53000 等。
            "ticks": 5000,
            // 当为 true 时,允许在命令中建议时间标记。
            // 如果为 false,仍然可以在命令中使用时间标记,
            // 只是不会被建议。
            "show_in_commands": true
        }
    }
    // ...
}

一旦定义了时间标记,它们就会在 ServerClockManager 中为世界时钟注册,从而允许它们被给定 ResourceKey 使用。

// 对于某个 ServerLevel level
// 假设我们有某个 ResourceKey<WorldClock> EXAMPLE_CLOCK
// 假设我们有某个 ResourceKey<ClockTimerMarker> EXAMPLE_MARKER

// 获取时钟引用
Holder.Reference<WorldClock> clock = level.registryAccess().getOrThrow(EXAMPLE_CLOCK);

// 获取服务器时钟管理器
ServerClockManager clockManager = level.clockManager();

// 检查时间是否在指定的标记处
// 这应在每刻检查特定时间事件时使用
boolean atMarker = clockManager.isAtTimeMarker(clock, EXAMPLE_MARKER);

// 跳转到标记指定的时间
// 如果世界时钟在 3000,则将时钟时间设置为 5000
// 如果世界时钟在 6000,则将时钟时间设置为 29000
// 返回时间是否被设置,如果标记对于时钟存在,则始终为 true。
boolean timeSet = clockManager.skipToTimeMarker(clock, EXAMPLE_MARKER);
  • net.minecraft.client.ClientClockManager - 在客户端管理世界时钟的滴答。
  • net.minecraft.client.gui.components.debug.DebugEntryDayCount - 显示 Minecraft 世界的当前日期。
  • net.minecraft.client.multiplayer
    • ClientLevel
      • setTimeFromServer 不再接受 long 白天时间,也不再接受是否滴答白天时间的 boolean
      • $ClientLevelData#setDayTime 已移除
    • ClientPacketListener#clockManager - 获取客户端时钟管理器。
  • net.minecraft.client.renderer.EndFlashState#tick 现在接受结束时钟时间而不是游戏时间
  • net.minecraft.commands.arguments.ResourceArgument
    • getClock - 根据字符串资源标识符获取世界时钟的引用。
    • getTimeline - 根据字符串资源标识符获取时间线的引用。
  • net.minecraft.core.registries.Registries#WORLD_CLOCK - 世界时钟的注册表标识符。
  • net.minecraft.gametest.framework.TestEnvironmentDefinition
    • $TimeOfDay -> $ClockTime,不是一对一
    • $Timelines - 一个使用时间线列表的测试环境。
  • net.minecraft.network.protocol.game.ClientboundSetTimePacket 现在接受一个时钟到其网络状态的映射,而不是白天时间 longboolean
  • net.minecraft.server
    • MinecraftServer
      • forceTimeSynchronization -> forceGameTimeSynchronization,不是一对一
      • clockManager - 服务器时钟管理器。
  • net.minecraft.server.level.ServerLevel
    • setDayTimegetDayCount 已移除
    • setEnvironmentAttributes - 设置要使用的环境属性系统。
  • net.minecraft.world.attribute.EnvironmentAttributeSystem$Builder#addTimelineLayer 现在接受 ClockManager 而不是 LongSupplier
  • net.minecraft.world.clock
    • ClockManager - 一个管理器,获取世界时钟已过去的刻数总数。
    • ClockNetworkState - 要在网络上同步的时钟的当前状态。
    • ClockState - 时钟的当前状态,包括总刻数和时钟是否暂停。
    • ClockTimeMarker - 一个跟踪世界时钟某个时间段的标记。
    • ClockTimeMarkers - 所有原版时间标记。
    • PackedClockStates - 一个时钟到其状态的映射,为存储或其他用途而压缩。
    • ServerClockManager - 在服务器端管理世界时钟的滴答。
    • WorldClock - 一个表示某个位置计时键的空记录。
    • WorldClocks - 所有原版世界时钟。
  • net.minecraft.world.level
    • Level
      • getDayTime -> getOverworldClockTime,不是一对一
      • clockManager - 时钟管理器。
      • getDefaultClockTime - 获取当前维度的时钟时间。
    • LevelReader#getEffectiveSkyBrightness - 使用当前变暗因子获取天空亮度。
  • net.minecraft.world.level.dimension.DimensionType 现在接受一个默认的、持有者包装的 WorldClock
  • net.minecraft.world.level.storage
    • LevelData#getDayTime 已移除
    • ServerLevelData
      • setDayTime 已移除
      • setClockStatesclockStates - 处理世界时钟的当前状态。
  • net.minecraft.world.level.storage.loot.predicates.TimeCheck 现在接受一个持有者包装的 WorldClock
    • time 现在接受一个持有者包装的 WorldClock
    • $Builder 现在接受一个持有者包装的 WorldClock
  • net.minecraft.world.timeline
    • AttributeTrack#bakeSampler 现在接受一个持有者包装的 WorldClock
    • AttributeTrackSampler 现在接受一个持有者包装的 WorldClock,以及一个 ClockManager 而不是用于白天时间获取器的 LongSupplier
    • Timeline 现在接受一个持有者包装的 WorldClock 以及一个时间标记到其信息的映射
      • #builder 现在接受一个持有者包装的 WorldClock
      • getPeriodCount - 获取在给定时间范围内已发生的周期数。
      • getCurrentTicks 现在接受 ClockManager 而不是 Level
      • getTotalTicks 现在接受 ClockManager 而不是 Level
      • clock - 返回持有者包装的 WorldClock
      • registerTimeMarkers - 注册此时间线中定义的所有 ClockTimeMarker
      • createTrackSampler 现在接受 ClockManager 而不是用于白天时间获取器的 LongSupplier
      • $Builder#addTimeMarker - 在给定刻数添加一个时间标记,以及是否可以在命令中建议该标记。
    • Timelines#DAY -> OVERWORLD_DAY

将主关卡数据拆分为保存数据

一些 WorldData 设置已移至 SavedData,允许等级/维度具有更多可定制性。这一增加还带来了一些关于如何引用和查询 SavedData 的变化。

保存数据变更

SavedDataType 现在使用 Identifier 标识某些 SavedData,该标识符针对数据文件夹进行解析。此更改允许数据文件夹内的子目录,因为数据存储将在尝试写入文件之前首先创建所有缺失的父目录。

public class ExampleData extends SavedData {

    public static final SavedDataType<ExampleData> TYPE = new SavedDataType<>(
        // 要解析的保存数据的标识符
        // 数据可以在以下位置找到:
        // `<world_folder>/dimensions/<dimension_namespace>/<dimension_path>/data/examplemod/example/data.dat`
        Identifier.fromNamespaceAndPath("examplemod", "example/data"),
        // 创建新保存数据的构造函数
        ExampleData::new,
        // 序列化新保存数据的编解码器
        MapCodec.unitCodec(ExampleData::new),
        // 数据修复器类型
        // 要么是一些修补的枚举值,要么根据模组加载器实现为 null。
        null
    );
}

然后可以通过 SavedDataStorage(从 DimensionDataStorage 重命名而来)查询 SavedData。重命名是因为 MinecraftServer 实例现在除了等级之外,还有自己的用于全局实例的数据存储。这意味着任何全局保存的数据都应存储在服务器实例上,而不是主世界。

// 给定一个 MinecraftServer server
ExampleData data = server.getDataStorage().computeIfAbsent(ExampleData.TYPE);


// 给定一个 ServerLevel level
ExampleData data = level.getDataStorage().computeIfAbsent(ExampleData.TYPE);

额外的保存数据

以下信息现在存储为保存数据:

  • 自定义 Boss 事件
  • 末影龙战斗
  • 游戏规则
  • 流浪商人生成
  • 天气
  • 世界生成设置

其中,只有末影龙战斗是基于每个等级/维度的。其余仍然通过服务器数据存储存储和访问。另一方面,自定义 Boss 事件仍然是唯一的,因为它由实现者决定哪些玩家参与事件。

  • net.minecraft.client.Minecraft#doWorldLoad 现在接受可选的 GameRules
  • net.minecraft.client.gui.screens.worldselection
    • CreateWorldCallback 现在接受 LevelDataAndDimensions$WorldDataAndGenSettings 和可选的 GameRules,而不是 PrimaryLevelData
    • EditGameRulesScreen -> AbstractGameRulesScreen
      • 实现在 .screens.options.InWorldGameRulesScreenWorldCreationGameRulesScreen
    • WorldOpenFlows
      • createLevelFromExistingSettings 现在接受 LevelDataAndDimensions$WorldDataAndGenSettings 和可选的 GameRules,而不是 WorldData
      • loadWorldStem 现在接受 LevelStorageSource$LevelStorageAccess
  • net.minecraft.client.server.IntegratedServer 现在接受可选的 GameRules
  • net.minecraft.server
    • MinecraftServer 现在接受可选的 GameRules
      • getGlobalGameRules - 获取主世界维度的游戏规则。
      • getWorldGenSettings - 获取世界的生成设置。
      • getWeatherData - 获取服务器的天气数据。
      • getDataStorage - 获取服务器的保存数据存储。
      • getGameRules - 获取服务器的游戏规则。
    • WorldStem 现在接受 LevelDataAndDimensions$WorldDataAndGenSettings 而不是 WorldData
  • net.minecraft.server.bossevents
    • CustomBossEvent 现在接受一个 UUID 作为标识符,以及一个 Runnable 作为回调
      • getTextId -> customId
      • addOfflinePlayer 已移除
      • getValue -> value
      • getMax -> max
      • load 现在接受 UUID 标识符以及一个 Runnable 作为回调
    • CustomBossEvents 现在扩展 SavedData
      • create 现在接受一个 RandomSource
      • saveload -> TYPE,不是一对一
  • net.minecraft.server.dedicated.DedicatedServer 现在接受可选的 GameRules
  • net.minecraft.server.level
    • ChunkMap#getChunkDataFixContextTag 现在接受一个可选的 Identifier 而不是 ResourceKey
    • ServerBossEvent 现在接受一个 UUID 作为 id
      • setDirty - 将 boss 事件标记为脏以进行保存。
    • ServerLevel 不再接受 RandomSequences
      • setWeatherParameters -> MinecraftServer#setWeatherParameters
      • getWeatherData - 获取服务器的天气数据。
      • getRandomSequence -> MinecraftServer#getRandomSequence
      • getRandomSequences -> MinecraftServer#getRandomSequences
  • net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner 现在接受 SavedDataStorage 而不是 ServerLevelData
    • MIN_SPAWN_CHANCE 现在从 private 变为 public
  • net.minecraft.world.entity.raid.Raids#TYPE_ENDgetType 已移除
  • net.minecraft.world.level
    • Level#prepareWeather 已移除
    • LevelSettings 现在是一个记录
      • 构造函数现在接受 $DifficultySettings 而不是仅仅 Difficulty
      • withDifficultyLock - 带有难度是否锁定的设置。
      • copy - 复制设置。
      • $DifficultySettings - 难度的设置。
  • net.minecraft.world.level.dimension.DimensionType 现在接受一个 boolean,表示维度是否可以有末影龙战斗
  • net.minecraft.world.level.dimension.end
    • DragonRespawnAnimation -> DragonRespawnStage,不是一对一
    • EndDragonFight -> EnderDragonFight,不是一对一
  • net.minecraft.world.level.gamerules.GameRuleMap 现在扩展 SavedData
    • TYPE - 保存数据类型。
    • reset - 将规则重置为其默认值。
  • net.minecraft.world.level.levelgen.WorldGenSettings 现在是一个 final 类而不是记录,扩展 SavedData
    • encodedecodeTYPE 取代
    • of - 构造生成设置。
  • net.minecraft.world.level.saveddata
    • SavedDataType 现在接受 Identifier 而不是字符串作为 id
    • WanderingTraderData - 流浪商人的保存数据。
    • WeatherData - 天气的保存数据。
  • net.minecraft.world.level.storage
    • DimensionDataStorage -> SavedDataStorage,不是一对一
    • LevelData#isThunderingisRainingsetRaining 现在在 WeatherData
    • LevelDataAndDimensions 现在接受 $WorldDataAndGenSettings 而不是 WorldData
      • $WorldDataAndGenSettings - 保存世界数据和生成设置。
    • LevelResource 现在是一个记录
    • PrimaryLevelData 字段已移至各自的保存数据类
      • PLAYER -> OLD_PLAYER
      • SINGLEPLAYER_UUID - 一个表示单机世界中玩家 UUID 的字符串。
      • WORLD_GEN_SETTINGS -> OLD_WORLD_GEN_SETTINGS
      • writeLastPlayed - 写入最后玩的玩家。
      • writeVersionTag - 写入数据版本标签。
    • ServerLevelData
      • setThunderinggetRainTimesetRainTimesetThunderTimegetThunderTimegetClearWeatherTimesetClearWeatherTime 移至 WeatherData
      • getWanderingTraderSpawnDelaysetWanderingTraderSpawnDelaygetWanderingTraderSpawnChancesetWanderingTraderSpawnChancegetWanderingTraderIdsetWanderingTraderId 移至 WanderingTraderData
      • getLegacyWorldBorderSettingssetLegacyWorldBorderSettingsWorldBorder 取代
      • getScheduledEvents -> MinecraftServer#getScheduledEvents
      • getGameRulesGameRuleMap 取代
    • WorldData
      • getCustomBossEventssetCustomBossEventsCustomBossEvents 取代
      • createTag 不再接受 RegistryAccess
      • getGameRulesGameRuleMap 取代
      • getLoadedPlayerTag -> getSinglePlayerUUID,不是一对一
      • endDragonFightDatasetEndDragonFightDataEnderDragonFight 取代
      • worldGenOptionsWorldGenSettings 保存数据取代
  • net.minecraft.world.level.timers.TimerQueue 现在扩展 SavedData
    • 构造函数现在接受 $Packed 事件,而不是 TimerCallbacks 和事件数据的 Stream
    • storeCODECTYPEcodec 取代
    • loadEventstoreEvent$Event$Packed#codec 取代
    • $Event 现在是一个记录
      • $Packed - 打包的事件数据。
    • $Packed - 打包的时间队列。

更多渲染变更

材质与动态层选择

方块和物品模型现在不再指定它们属于哪个 RenderTypeChunkSectionLayer。相反,这在加载模型时计算,确定每个四边形的关联层。这意味着 ItemBlockRenderTypes 被移除,物品的 RenderType 设置也被完全移除。

为了确定四边形或面被设置到哪个层,会计算纹理的 Transparency。具体来说,对于映射到四边形的 UV 区域,检查是否存在任何透明像素(alpha 为 0)或半透明像素(alpha 不为 0 或 255)。对于 ChunkSectionLayer,如果存在半透明像素则使用 ChunkSectionLayer#TRANSLUCENT,否则如果存在透明像素则使用 CUTOUT,否则使用 SOLID。对于物品 RenderType,如果存在半透明像素则使用 Sheets#translucentItemSheet 和用于方块物品的 translucentBlockItemSheet,否则使用 cutoutItemSheet 和用于方块物品的 cutoutBlockItemSheetTransparency 也影响 MipmapStrategy#AUTO 的使用,如果存在透明像素则使用 CUTOUT 而不是 MEAN 作为默认值。

可以通过模型 JSON 定义的 Material 纹理来影响四边形的 Transparency。一个 Material 指定纹理的 sprite,它表示纹理的相对路径,以及可选的 force_translucent,它强制使用此纹理的任何四边形使用 Transparency#TRANSLUCENT(透明为 false,半透明为 true):

// 对于某个模型 `examplemod:example_model`
// 在:`assets/examplemod/models/example_model.json`
{
    "parent": "minecraft:block/template_glass_pane_post",
    "textures": {
        // Material 可以是一个简单的纹理引用
        // 指向 `assets/minecraft/textures/block/glass_pane_top.png`
        "edge": "minecraft:block/glass_pane_top",
        // 或者它可以是一个对象
        "pane": {
            // 使用此键的面的相对纹理引用
            // 指向 `assets/minecraft/textures/block/glass.png`
            "sprite": "minecraft:block/glass",
            // 当为 true 时,将此纹理键的所有面设置为
            // 始终具有透明像素。
            "force_translucent": true
        }
    }
    // ...
}

此更改还定义了渲染顺序,其中所有实体四边形首先渲染,然后是切割四边形,最后是半透明四边形,按距离相机的距离排序。

材质与精灵

您可能已经注意到,Material 最初用于定义图集中的某些纹理。纹理 JSON 中材质的添加改变了这些类的命名。Material 现在明确指代模型 JSON 中的纹理引用。这意味着,所有对原始纹理位置的引用都已替换为 Material(如果未烘焙)和 Material$Baked(如果已烘焙)。此外,SpriteGetter 现在是 MaterialBaker

至于原来的 Material,现在称为精灵,其中 Material 重命名为 SpriteIdMaterialSet 重命名为 SpriteGetter

四边形粒子层

SingleQuadParticle$Layer 已拆分为 OPAQUE_*TRANSLUCENT_* 层,具体取决于图集使用的粒子纹理是否包含半透明像素。请注意,这里的“opaque”指的是切割,其中 alpha 小于 0.1 的像素被丢弃。如果不创建新层,可以使用 $Layer#bySprite 来确定粒子纹理应使用的层。

public class ExampleParticle extends SingleQuadParticle {

    private final SingleQuadParticle.Layer layer;

    public SingleQuadParticle(ClientLevel level, double x, double y, double z, TextureAtlasSprite sprite) {
        super(level, x, y, z, sprite);
        this.layer = SingleQuadParticle.Layer.bySprite(sprite);
    }

    @Override
    protected SingleQuadParticle.Layer getLayer() {
        return this.layer;
    }
}

方块模型

在通用世界上下文之外渲染单个方块模型的管道已被重写,类似于 ItemModel,其中“方块模型”更新某个渲染状态,然后提交其元素进行渲染。因此,大多数方块模型类已被重写或在一定程度上重新组织。

由于方块模型名称通常与通用模型 JSON 同义,许多类被移动和重命名,以将模型 JSON 与方块状态 JSON 以及现在的方块模型分开。因此,原始名称中带有“block”的模型几何体已更改为“cuboid”:(例如,BlockModel -> CuboidModelBlockModelWrapper -> CuboidItemModelWrapper)。此外,引用方块状态 JSON 内定义的渲染过程部分已从“block”更改为“block state”(例如,BlockModelPart -> BlockStateModelPartBlockModelDefinition -> BlockStateModelDispatcher)。您可以认为大多数“block model”类是新的,而那些重命名的类取代了 SpecialBlockModelRenderer 系统。

方块模型系统从所有模型和定义加载并解析后的 ModelManager 开始,准备进行烘焙。方块模型通过 BuiltInBlockModels#crateBlockModels 加载,它将某个 BlockState 链接到 BlockModel$Unbaked。与物品模型类似,未烘焙实例定义了应如何构建方块模型的属性。这些存储在 LoadedBlockModels 中,然后在所有 JSON 之后通过 bake 烘焙成 BlockModel。然后,这个 BlockStateBlockModel 的映射存储在 BlockModelSet 中,准备好通过 get 查询,或者更常见的是通过 BlockModelResolver#update 查询,后者调用模型集。任何未延迟定义的模型都会解析为 BlockStateModel 的包装器。

原版为常见用途提供了六种 BlockModel 实现。有 EmptyBlockModel,它不提交任何元素,因此不渲染任何内容;以及 BlockStateModelWrapper,它包装并显示关联的 BlockStateModel。然后,有根据某些属性开关更改模型的等价物(SelectBlockModel)、条件 booleanConditionalBlockModel)以及将多个模型组合在一起的组合(CompositeBlockModel)。最后,有 SpecialBlockModelWrapper,它通过存储的 SpecialModelRenderer 提交其元素,这是物品和方块模型之间的统一提交器。

// 由于方块模型系统通过其代码内引导程序进行硬编码,
// 此示例将假设存在某种方法来访问 `BuiltInBlockModels$Builder` 构建器。

// 我们还将假设我们有某个 Block EXAMPLE_BLOCK_* 来附加模型。

// 常规方块模型
builder.put(
    // 一个工厂,接受 `BlockColors` 和 `BlockState` 并返回
    // 一个 `BlockModel$Unbaked`。
    (colors, state) -> new BlockStateModelWrapper.Unbaked(
        // 要获取 `BlockStateModel` 的状态。
        state,
        // 模型的色调层。
        colors.getTintSources(state),
        // 在提交模型之前应用于 `PoseStack` 的可选变换。
        Optional.empty(new Transformation(new Matrix4f().translation(0.5f, 0.5f, 0.5f)))
    ),
    // 要使用此模型的方块。将为每个状态循环构造一个。
    EXAMPLE_BLOCK_1
);

// 根据某些属性切换的方块模型
builder.put(
    (colors, state) -> new SelectBlockModel.Unbaked(
        // 在提交模型之前应用于 `PoseStack` 的可选变换。
        Optional.empty(),
        // 一个包含要切换的属性以及当应选择特定方块模型时的值的记录。
        new SelectBlockModel.UnbakedSwitch<>(
            // 要切换的 `SelectBlockModelProperty`。属性
            // 值从 `BlockState` 及其 `BlockDisplayContext` 确定。
            (state, displayContext) -> state.getRenderShape(),
            // 用于确定要使用哪个 `BlockModel` 的情况列表。
            List.of(
                new SelectBlockModel.SwitchCase<>(
                    // 此模型适用的值列表。
                    List.of(RenderShape.INVISIBLE),
                    // 当满足此属性时要使用的模型。
                    new EmptyBlockModel.Unbaked()
                )
            ),
            // 如果没有开关情况与状态属性匹配,则使用可选的后备。
            Optional.of(new EmptyBlockModel.Unbaked())
        )
    ),
    EXAMPLE_BLOCK_2
);

// 基于某些条件的方块模型
builder.put(
    (colors, state) -> new ConditionalBlockModel.Unbaked(
        // 在提交模型之前应用于 `PoseStack` 的可选变换。
        Optional.empty(),
        // 从 `BlockState` 确定 `boolean` 的 `ConditionalBlockModelProperty`。
        BlockState::isSignalSource,
        // 当属性返回 `true` 时要显示的模型。
        new EmptyBlockModel.Unbaked(),
        // 当属性返回 `false` 时要显示的模型。
        new EmptyBlockModel.Unbaked()
    ),
    EXAMPLE_BLOCK_3
);

// 一个组合方块模型
builder.put(
    (colors, state) -> new CompositeBlockModel.Unbaked(
        // 要显示的第一个模型。
        new EmptyBlockModel.Unbaked(),
        // 要显示的第二个模型。
        new EmptyBlockModel.Unbaked(),
        // 在提交模型之前应用于 `PoseStack` 的可选变换。
        Optional.empty()
    ),
    EXAMPLE_BLOCK_4
);

// 特殊方块模型
builder.put(
    (colors, state) -> new SpecialBlockModelWrapper.Unbaked(
        // 用于为模型提交元素的未烘焙 `SpecialModelRenderer`。
        new BellSpecialRenderer.Unbaked(),
        // 在提交模型之前应用于 `PoseStack` 的可选变换。
        Optional.empty()
    ),
    EXAMPLE_BLOCK_5
);

在功能提交过程中,方块模型通过 BlockModelResolverBlockModelRenderState 处理。这类似于其他渲染状态的工作方式。首先,BlockModelResolver#update 设置 BlockModelRenderState。设置通过基本路径处理——BlockModelRenderState#setupModel,将模型部件添加到返回的列表中,然后 setupTints,或者通过特殊渲染器的 setupSpecialModel。然后,渲染状态通过 BlockModelRenderState#submit 提交其元素进行渲染。渲染状态还提供 submitOnlyOutline,它使用轮廓渲染类型,以及 submitWithZOffset,它使用实体的前向 Z 偏移渲染类型。

// BlockEntity 示例
public class ExampleRenderState extends BlockEntityRenderState {
    // 持有渲染状态。
    public final BlockModelRenderState exampleBlock = new BlockModelRenderState();
}

public class ExampleRenderer implements BlockEntityRenderer<ExampleBlockEntity, ExampleRenderState> {

    // 用于方块实体渲染器的显示上下文。
    public static final BlockDisplayContext BLOCK_DISPLAY_CONTEXT = BlockDisplayContext.create();
    private final BlockModelResolver blockResolver;

    public ExampleRenderer(BlockEntityRendererProvider.Context ctx) {
        super(ctx);
        // 获取模型解析器。
        this.blockResolver = ctx.blockModelResolver();
    }

    @Override
    public void extractRenderState(ExampleBlockEntity blockEntity, ExampleRenderState state, float partialTick, Vec3 cameraPosition, ModelFeatureRenderer.CrumblingOverlay breakProgress) {
        super.extractRenderState(blockEntity, state, partialTick, cameraPosition, breakProgress);

        // 更新模型状态。
        this.blockResolver.update(state.exampleBlock, Blocks.DIRT.defaultBlockState(), BLOCK_DISPLAY_CONTEXT);
    }

    @Override
    public void submit(ExampleRenderState state, PoseStack pose, SubmitNodeCollector collector, CameraRenderState camera) {
        super.submit(state, pose, collector, camera);

        // 提交模型状态进行渲染。
        state.exampleBlock.submit(
            // 当前姿势堆栈,
            pose,
            // 节点收集器。
            collector,
            // 光照坐标。
            state.lightCoords,
            // 覆盖坐标。
            OverlayTexture.NO_OVERLAY,
            // 轮廓颜色。
            0
        );


    }
}

// Entity 示例
public class ExampleRenderState extends EntityRenderState {
    // 持有渲染状态。
    public final BlockModelRenderState exampleBlock = new BlockModelRenderState();
}

public class ExampleRenderer extends EntityRenderer<ExampleEntity, ExampleRenderState> {

    // 用于实体渲染器的显示上下文。
    public static final BlockDisplayContext BLOCK_DISPLAY_CONTEXT = BlockDisplayContext.create();
    private final BlockModelResolver blockResolver;

    public ExampleRenderer(EntityRendererProvider.Context ctx) {
        super(ctx);
        // 获取模型解析器。
        this.blockResolver = ctx.getBlockModelResolver();
    }

    @Override
    public void extractRenderState(ExampleEntity entity, ExampleRenderState state, float partialTick) {
        super.extractRenderState(entity, state, partialTick);

        // 更新模型状态。
        this.blockResolver.update(state.exampleBlock, Blocks.DIRT.defaultBlockState(), BLOCK_DISPLAY_CONTEXT);
    }

    @Override
    public void submit(ExampleRenderState state, PoseStack pose, SubmitNodeCollector collector, CameraRenderState camera) {
        super.submit(state, pose, collector, camera);

        // 提交模型状态进行渲染。
        state.exampleBlock.submit(
            // 当前姿势堆栈。
            pose,
            // 节点收集器。
            collector,
            // 光照坐标。
            state.lightCoords,
            // 覆盖坐标。
            OverlayTexture.NO_OVERLAY,
            // 轮廓颜色。
            state.outlineColor
        );
    }
}

方块色调源

BlockColor 已被完全替换为 BlockTintSource,它根据所需的上下文设置特定索引的 ARGB 色调。色调源可以提供三种上下文:

  • color 用于通用上下文,由 BlockModel 使用
  • colorInWorld 用于世界上下文,由 ModelBlockRenderer#tesselateBlock 使用
  • colorAsTerrainParticle 用于粒子上下文,由下落的灰尘和地形粒子使用

此外,如果使用 BlockStateProperty 来确定要染色的颜色,BlockTintSource 会提供 relevantProperties。这被 LevelRenderer 用来确定状态更改是否需要重新渲染模型。

BlockTintSource 仍然通过 register 注册到 BlockColors,接受一个源列表,后跟可变参数的方块。模型 JSON 中指定的 tintindex 用于索引到色调源列表中。

// 假设可以访问 BlockColors colors
colors.register(
    // 要应用于某个方块模型的色调列表。
    List.of(
        // "tintindex": 0
        (state) -> 0xFFFF0000,
        // "tintindex": 1
        new BlockTintSource() {

            @Override
            public int color(BlockState state) {
                return 0xFF00FF00;
            }

            @Override
            public int colorInWorld(BlockState state, BlockAndTintGetter level, BlockPos pos) {
                return 0xFF0000FF;
            }
        }
    ),
    // 这些色调源将应用的方块。
    EXAMPLE_BLOCK_1
);

移除旧的方块和物品渲染器

由于 ItemModelBlockModel 现在完全通过它们自己的功能提交管道处理,BlockRenderDispatcherItemRenderer 已被完全移除,被相应的系统取代。

对象定义变换

ItemModelBlockModel 现在可以接受一个可选的 Transformation,它变换模型应如何显示。因此,$Unbaked#bake 方法现在接受父级 Matrix4fc 变换,变换通过 Transformation#compose 乘以此变换。对于物品模型,这被称为独立于模型 JSON 物品变换的局部变换。局部变换总是在物品变换之后应用。

请注意,添加对变换的支持应始终通过 Transformation#compose 完成,因为传递的矩阵本质上是可变的。假设任何不通过原版接口执行的自定义方法应在执行任何修改之前进行复制。

四边形实例

亮度/色调颜色、光照图和覆盖坐标已被合并到一个单一对象中:QuadInstance。这个可变类通过其关联的 set* 方法设置值,并可以通过 get* 方法为每个四边形顶点提取信息。亮度和色调作为颜色存储在一起,而不是两个单独的值。

QuadInstance 并不取代所有用例,例如添加单个顶点时。它仅更新 VertexConsumer 的方法,将 putBulkData 拆分为用于方块模型中四边形的 putBlockBakedQuad,以及用于所有其他用途的 putBakedQuad

此外,许多用于将 BakedQuad 上传到缓冲区的方法现在接受一个 BlockQuadOutput。它具有与 VertexConsumer#putBlockBakedQuad 相同的参数,并且由于部分渲染器上传到新分配的 BufferBuilder 以用于超级缓冲区而添加。

GUI 提取器

GUI 类方法经历了一个大规模的重命名方案,表明提交的元素被“提取”到一个通用树中以进行提交然后渲染。因此,以 draw*render* 开头的方法现在以 extract* 为前缀,并可能以 *RenderState 为后缀(例如,Renderable#render -> extractRenderStateAbstractContainerScreen#renderLabels -> extractLabelsAbstractWidget#renderWidget -> extractWidgetRenderState)。一些缩写也被扩展,要么通过重命名,要么用另一个方法替换(例如,AbstractContainerScreen#renderBgScreen#extractBackground 取代)。

GuiGraphics 也以同样的方式重命名为 GuiGraphicsExtractor。这些方法遵循与 GUI 其余部分类似的模式(例如,hline -> horizontalLine),不同之处在于 draw*render*submit* 前缀以及 *RenderState 后缀被移除(例如,renderOutline -> outlinesubmitEntityRenderState -> entity)。唯一的重命名是 *String* 方法名称被替换为 *Text*

流体模型

定义流体的纹理和色调现已从 FluidRenderer(以前称为 LiquidBlockRenderer)中移出,并移入其自己的 FluidModel 记录中。最初,由于流体数量较少,未烘焙变体(FluidModel$Unbaked)存储为常量。然后,在 BlockModel 烘焙之后,流体模型通过 FluidStateModelSet#bake 烘焙,将 Fluid 链接到其 FluidModel。然后,此映射存储在 FluidStateModelSet 中,准备好通过 get 查询。

一个 FluidModel$Unbaked 有四个参数:三个用于静态、流动和可选覆盖纹理的 Material;以及一个用于 BlockTintSource 的参数。色调通过 BlockTintSource#colorInWorld 获得。在烘焙过程中,它将根据提供的材质的透明度确定 ChunkSectionLayer

// 由于流体模型系统在其烘焙中被硬编码,此示例
// 将假设存在某种方法可以修改访问
// `FluidStateModelSet#bake` 返回的 `Map<Fluid, FluidModel>` fluidModels。

// 我们还将假设我们有某个 Fluid EXAMPLE_FLUID* 来附加模型。

FluidModel.Unbaked exampleFluidModel = new FluidModel.Unbaked(
    // 静态流体的纹理。
    new Material(
        // 纹理的相对标识符。
        // 指向 `assets/examplemod/textures/block/example_fluid_still.png`
        Identifier.fromNamespaceAndPath("examplemod", "block/example_fluid_still"),
        // 当为 true 时,将此纹理键的所有面设置为
        // 始终具有透明像素。
        true
    ),
    // 流动流体的纹理。
    new Material(Identifier.fromNamespaceAndPath("examplemod", "block/example_fluid_flowing")),
    // 如果不为 null,则当流体侧面被 `HalfTransparentBlock` 或 `LeavesBlock` 遮挡时使用的覆盖纹理。
    null,
    // 如果不为 null,则在世界中时应用于流体纹理的色调源。
    null
);

// 假设我们可以访问 `MaterialBaker` materials。

FluidModel exampleBakedFluidModel = exampleFluidModel.bake(
    // 用于获取材质图集精灵的烘焙器。
    materials,
    // 一个提供的调试名称,以正确报告哪些模型
    // 缺少纹理。
    () -> "examplemod:example_fluid_model"
);

fluidModels.put(
    // 模型应使用的流体。
    EXAMPLE_FLUID,
    // 烘焙的流体模型。
    exampleBakedFluidModel
);
fluidModels.put(EXAMPLE_FLUID_FLOWING, exampleBakedFluidModel);

名称标签偏移

EntityRenderer#submitNameTag 已重命名为 submitNameDisplay,现在可以选择接受名称标签附件的 y 偏移。

色调获取器

BlockAndTintGetter 现在是一个附加到 ClientLevel 的客户端专用接口。它以前的用途被 BlockAndLightGetter 取代——BlockAndTintGetter 现在扩展了它——并剥离了色调和光照方向。

管道深度和颜色

RenderPipeline 中定义的深度和颜色方法已被合并到两个状态对象中。

DepthTestFunction、写入 boolean 以及偏置 float 现在存储在 DepthStencilState 中。DepthTestFunction 已被更通用的 CompareOp 取代,后者定义了如何比较两个数字。每个函数都有一个简单的等价物,NO_DEPTH_TESTCompareOp#ALWAYS_PASS 取代。深度信息可以通过 RenderPipeline$Builder#withDepthStencilState 添加到管道中。

可选的 BlendFunction 以及颜色/alpha boolean 现在存储在 ColorTargetState 中。boolean 被合并到一个 int 中,使用低四位作为标志:1 是红色,2 是绿色,4 是蓝色,8 是 alpha。颜色 boolean 使用 7 表示红色、绿色和蓝色;alpha boolean 使用 8;而两者结合使用 15LopicOp 已被完全移除。颜色信息可以通过 RenderPipeline$Builder#withColorTargetState 添加到管道中。

public static final RenderPipeline EXAMPLE_PIPELINE = RenderPipeline.builder()
    .withLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "pipeline/example"))
    .withVertexShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
    .withFragmentShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
    .withVertexFormat(DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS)
    .withShaderDefine("ALPHA_CUTOUT", 0.5)
    .withSampler("Sampler0")
    .withUniform("ModelOffset", UniformType.VEC3)
    .withUniform("CustomUniform", UniformType.INT)
    .withPolygonMode(PolygonMode.FILL)
    .withCull(false)
    // 在写入缓冲区数据时设置颜色目标。
    .withColorTargetState(new ColorTargetState(
        // 指定将两个带有 alpha 的颜色混合在一起时要使用的函数。
        // 由 `SourceFactor` 和 `DestFactor` 组成。
        // 前两个用于 RGB,后两个用于 alpha。
        // 如果 optional 为空,则禁用混合。
        Optional.of(BlendFunction.TRANSLUCENT),
        // 确定将哪些颜色写入缓冲区的掩码。
        // 表示为四位值
        // 0001 - 写入红色通道。
        // 0010 - 写入绿色通道。
        // 0100 - 写入蓝色通道。
        // 1000 - 写入 alpha 通道。
        ColorTargetState.WRITE_RED | ColorTargetState.WRITE_GREEN | ColorTargetState.WRITE_BLUE | ColorTargetState.WRITE_ALPHA
    ))
    // 在写入缓冲区数据时设置深度模板。
    .withDepthStencilState(new DepthStencilState(
        // 设置在离相机不同距离处渲染对象时要使用的深度测试函数。
        // 值:
        // - ALWAYS_PASS           (GL_ALWAYS)
        // - LESS_THAN             (GL_LESS)
        // - LESS_THAN_OR_EQUAL    (GL_LEQUAL)
        // - EQUAL                 (GL_EQUAL)
        // - NOT_EQUAL             (GL_NOTEQUAL)
        // - GREATER_THAN_OR_EQUAL (GL_GEQUAL)
        // - GREATER_THAN          (GL_GREATER)
        // - NEVER_PASS            (GL_NEVER)
        CompareOp.LESS_THAN_OR_EQUAL,
        // 是否屏蔽写入值到深度缓冲区
        false,
        // 用于计算多边形深度值的比例因子。
        0f,
        // 用于计算多边形深度值的单位偏移。
        0f
    ))
    .build()
;

Blaze3d 后端

CommandEncoderGpuDeviceRenderPassBackend 已拆分为 *Backend 接口,其功能类似于以前的接口,以及包装器类,它持有后端并提供委托调用,执行任何必要的验证。*Backend 接口现在显式执行操作,而不检查操作是否有效。

实体和半透明功能

功能渲染已进一步拆分为两个通道:一个用于实体渲染类型,一个用于半透明渲染类型。因此,大多数 render 方法现在分别具有 renderSolidrenderTranslucent 方法。那些只渲染实体或半透明数据的方法只具有其中一个方法。

相机状态

Camera 已更新,类似于其他渲染状态实现,其中相机在 GameRenderer#renderLevel 期间被提取到 CameraRenderState,并传递带有提交和渲染元素所需的数据。

由于此更改,FogRenderer#setupFog 现在返回 FogData,其中包含渲染雾所需的所有信息,而不仅仅是其颜色,并将其存储在 CameraRenderState#fogData 中。

  • assets/minecraft/shaders/core 中的一些着色器现在使用 texture 而不是 texelFetch
    • entity.vsh
    • item.vsh
    • rendertype_leash.vsh
    • rendertype_text.vsh
    • rendertype_text_background.vsh
    • rendertype_text_intensity.vsh
  • assets/minecraft/shaders/core
    • block.vsh#minecraft_sample_lightmap -> sample_lightmap.glsl#sample_lightmap
    • rendertype_crumbling 不再接受 texCoord2(光照图)
    • rendertype_entity_alpharendertype_entity_decal 合并到 entity.fsh 中,使用 DissolveMaskSampler
    • rendertype_item_entity_translucent_cull -> item,不是一对一
    • rendertype_translucent_moving_block 已移除
      • 现在使用 ChunkSectionLayer 提供的着色器
  • com.mojang.blaze3d
    • GLFWErrorCapture - 在 GL 过程中捕获错误。
    • GLFWErrorScope - 一个定义要捕获的 GL 错误范围的可关闭对象。
  • com.mojang.blaze3d.opengl
    • GlProgram#BUILT_IN_UNIFORMSINVALID_PROGRAM 现在是 final
    • GlBackend - OpenGL 的 GPU 后端。
    • GlCommandEncoder 现在实现 CommandEncoderBackend 而不是 CommandEncoder,该类现在是包私有的
      • getDevice 已移除
    • GlConst#toGl 现在接受 CompareOp 而不是 DepthTestFunction
    • GlDevice 现在实现 GpuDeviceBackend 而不是 GpuDevice,该类现在是包私有的
      • 构造函数现在接受 GpuDebugOptions,其中包含日志级别、是否使用同步日志以及是否使用调试标签,而不是直接传入这些参数
    • GlRenderPass 现在实现 RenderPassBackend 而不是 RenderPass,该类现在是包私有的
      • 构造函数现在接受 GlDevice
    • GlStateManager#_colorMask 现在接受 int 作为颜色掩码,而不是四个 boolean
  • com.mojang.blaze3d.platform
    • ClientShutdownWatchdog 现在接受 Minecraft 实例
    • DebugMemoryUntracker#untrack 已移除
    • GLX#make(T, Consumer) 已移除
    • NativeImage
      • computeTransparency - 返回图像中是否至少有一个透明或半透明像素。
        • 如果图像面积大于 512MiB,或带有颜色数据时大于 2GiB,则会崩溃。
      • isClosed - 图像是否已关闭或释放。
    • Transparency - 一个关于某个图像是否具有半透明和/或透明像素的对象。
    • Window 现在接受 GpuBackend 而不是 ScreenManager
      • createGlfwWindow - 直接使用提供的设置创建 GLFW 窗口。
      • updateDisplay -> updateFullscreenIfChanged,不是一对一
      • isResizedresetIsResized - 处理窗口是否已调整大小。
      • backend - 返回 GpuBackend
      • $WindowInitFailed 构造函数现在从 private 变为 public
    • WindowEventHandler#resizeDisplay -> resizeGui
  • com.mojang.blaze3d.pipeline
    • ColorTargetState - 一个包含颜色混合函数和掩码的记录。
    • DepthStencilState - 一个包含深度模板数据的记录。
    • RenderPipeline 现在接受 ColorTargetState 而不是可选的 BlendFunction、颜色和 alpha boolean 以及 LogicOp;以及 DepthStencilState 而不是 DepthTestFunction、深度 boolean 和偏置 float
      • getDepthTestFunctionisWriteDepthgetDepthBiasScaleFactorgetDepthBiasConstant -> getDepthStencilState,不是一对一
      • getColorLogicgetBlendFunctionisWriteColorisWriteAlpha -> getColorTargetState,不是一对一
      • $Builder
        • withDepthTestFunctionwithDepthWritewithDepthBias -> withDepthStencilState,不是一对一
        • withBlendwithColorWritewithColorLogic -> withColorTargetState,不是一对一
      • $Snippet 现在接受 ColorTargetState 而不是可选的 BlendFunction、颜色和 alpha boolean 以及 LogicOp;以及 DepthStencilState 而不是 DepthTestFunction 和深度 boolean
  • com.mojang.blaze3d.platform
    • BackendOptions - 用于初始化后端的配置。
    • DepthTestFunction -> CompareOp,不是一对一
      • NO_DEPTH_TEST -> CompareOp#ALWAYS_PASS
      • EQUAL_DEPTH_TEST -> CompareOp#EQUAL
      • LEQUAL_DEPTH_TEST -> CompareOp#LESS_THAN_OR_EQUAL
      • LESS_DEPTH_TEST -> CompareOp#LESS_THAN
      • GREATER_DEPTH_TEST -> CompareOp#GREATER_THAN
    • GLX
      • _initGlfw 现在接受 BackendOptions
      • glfwBool - true1false0
    • LogicOp 枚举已移除
  • com.mojang.blaze3d.shaders.GpuDebugOptions - GPU 管线的调试选项。
  • com.mojang.blaze3d.systems
    • BackendCreationException - 当无法创建 GPU 后端时抛出的异常。
    • CommandEncoder -> CommandEncoderBackend
      • 原始接口现在是一个围绕接口的类包装器,在执行验证检查后委托给后端
    • GpuBackend - 一个负责创建使用的 GPU 设备和显示窗口的接口。
    • GpuDevice -> GpuDeviceBackend
      • 原始接口现在是一个围绕接口的类包装器,在执行验证检查后委托给后端
      • setVsync - 设置是否启用 VSync。
      • presentFrame - 交换窗口的前后缓冲区以显示当前帧。
      • isZZeroToOne - 是否使用 0 到 1 的 Z 范围而不是 -1 到 1。
    • RenderPass -> RenderPassBackend
      • 原始接口现在是一个围绕接口的类包装器,在执行验证检查后委托给后端
    • RenderSystem
      • pollEvents 现在是公开的
      • flipFrame 不再接受 Window
      • initRenderer 现在只接受 GpuDevice
      • limitDisplayFPS -> FramerateLimiter#limitDisplayFPS
      • initBackendSystem 现在接受 BackendOptions
  • com.mojang.blaze3d.vertex
    • DefaultVertexFormat#BLOCK 不再接受法线向量
    • PoseStack#mulPose$Pose#mulPose 现在有一个接受 Transformation 的重载
    • QuadInstance - 一个包含四边形颜色、光照坐标和覆盖的类。
    • TlsfAllocator - 一个用于动态内存分配的两级隔离适配分配器。
    • UberGpuBuffer - 一个用于将动态大小的数据上传到 GPU 的缓冲区,用于区块部分层。
    • VertexConsumer
      • putBulkData -> putBlockBakedQuadputBakedQuad;不是一对一
        • 亮度 float 数组、颜色 float、光照图 int 数组和覆盖 intQuadInstance 取代
        • putBlockBakedQuadPoseStack$Pose 替换为 XYZ float 方块位置
      • addVertex(PoseStack$Pose, Vector3f) -> addVertex(PoseStack$Pose, Vector3fc)
      • setNormal(PoseStack$Pose, Vector3f) -> setNormal(PoseStack$Pose, Vector3fc)
  • com.mojang.math
    • MatrixUtil
      • checkPropertyRaw 现在从 private 变为 public
      • isOrthonormal 已移除
    • Transformation
      • IDENTITY 现在从 private 变为 public
        • 取代了 identity 方法
      • getTranslation -> translation
      • getLeftRotation -> leftRotation
      • getScale -> scale
      • getRightRotation -> rightRotation
      • compose - 如果存在,将变换应用于给定矩阵。
  • net.minecraft.SharedConstants
    • DEBUG_DUMP_INTERPOLATED_TEXTURE_FRAMES 已移除
    • DEBUG_PREFER_WAYLAND - 当为 true 时,如果同时支持 Wayland 和 X11,则阻止将平台初始化提示设置为 X11。
  • net.minecraft.client
    • Camera
      • BASE_HUD_FOV - 基础 HUD 视场角。
      • setup -> update,不是一对一
      • extractRenderState - 提取相机的状态。
      • getFov - 获取视场角。
      • getViewRotationMatrix - 获取投影视图的矩阵。
      • setEntity - 设置相机附加到的实体。
      • getNearPlane 现在接受 float 视场角
      • panoramicForwards - 全景模式下的前向向量。
      • getPartialTickTime 已移除
      • setLevel - 设置相机所在的等级。
      • getCameraEntityPartialTicks - 根据实体的状态获取部分刻。
    • DeltaTracker#advanceTimeadvanceGameTime(当 booleantrue 时)和 advanceRealTime 取代
      • advanceGameTimeadvanceRealTime 以前是 private,现在是 public
    • FramerateLimiter - 一个用于限制客户端帧率的实用程序。
    • Minecraft
      • noRender 已移除
      • useAmbientOcclusion 已移除
      • getBlockRenderer 已移除
      • getItemRenderer 已移除
    • Options
      • getCloudsType -> getCloudStatus
      • exclusiveFullscreen - 当为 true 时,全屏模式完全控制显示器。
  • net.minecraft.client.color.block
    • BlockColorBlockTintSource 取代,不是一对一
      • getColor -> colorInWorld, colorAsTerrainParticle; 不是一对一
    • BlockColors
      • getColorgetTintSourcesgetTintSource 取代;不是一对一
      • register 现在接受一个 BlockTintSource 列表而不是一个 BlockColor
    • BlockTintSource - 一个用于确定如何对 BlockState 进行单独或上下文着色的源。
    • BlockTintSources - 通用块着色源的实用程序。
  • net.minecraft.client.data.models
    • BlockModelGenerators
      • createSuffixedVariant 现在接受一个从 MaterialTextureMapping 的函数用于纹理,而不仅仅是 Identifier
      • createAirLikeBlock 现在接受一个 Material 而不是 Identifier 作为粒子纹理
      • generateSimpleSpecialItemModel 现在接受一个可选的 Transformation
      • createChest 现在有一个接受 MutiblockChestResources 纹理的重载
    • ItemModelGenerators#generateLayeredItem 现在接受 Material 而不是 Identifier 作为纹理
  • net.minecraft.client.data.models.model
    • ItemModelUtils
      • specialModel 现在有接受 Transformation 的重载
      • conditional 现在有接受 Transformation 的重载
      • select 现在有一个接受 Transformation 的重载
      • selectBlockItemProperty 现在有一个接受 Transformation 的重载
    • TexturedModel#createAllSame 现在接受一个 Material 而不是 Identifier 作为纹理
    • TextureMapping
      • putputForced 现在接受一个 Material 而不是 Identifier 作为纹理
      • get 现在返回一个 Material 而不是 Identifier 作为纹理
      • copyAndUpdate 现在接受一个 Material 而不是 Identifier 作为纹理
      • updateSlots - 使用提供的映射函数替换所有槽位。
      • forceAllTranslucent - 为所有材质纹理设置强制半透明标志。
      • defaultTexture, cube, cross, plant, rail, wool, crop, singleSlot, particle, torch, cauldron, layer0 现在接受一个 Material 而不是 Identifier 作为纹理
      • column, door, layered 现在接受 Material 而不是 Identifier 作为纹理
      • getBlockTeture, getItemTexture 现在返回一个 Material 而不是 Identifier 作为纹理
  • net.minecraft.client.entity.ClientAvatarEntity#belowNameDisplay -> Entity#belowNameDisplay
  • net.minecraft.client.gui
    • Font
      • drawInBatch, drawInBatch8xOutline 现在接受一个 Matrix4fc 而不是 Matrix4f 作为姿态
      • $GlyphVisitor#forMultiBufferSource 现在接受一个 Matrix4fc 而不是 Matrix4f 作为姿态
    • Gui
      • render* 方法已重命名为 extract*
      • render -> extractRenderState
      • $RenderFunction 接口已移除
    • GuiGraphics -> GuiGraphicsExtractor
      • hLine -> horizontalLine
      • vLine -> verticalLine
      • renderOutline -> outline
      • drawCenteredString -> centeredText
      • drawString -> text
      • drawStringWithBackdrop -> textWithBackdrop
      • renderItem -> item
      • renderFakeItem -> fakeItem
      • renderItemDecorations -> itemDecorations
      • submitMapRenderState -> map
      • submitEntityRenderState -> entity
      • submitSkinRenderState -> skin
      • submitBookModelRenderState -> book
      • submitBannerPatternRenderState -> bannerPattern
      • submitSignRenderState -> sign
      • submitProfilerChartRenderState -> profilerChart
      • renderTooltip -> tooltip
      • renderComponentHoverEffect -> componentHoverEffect,现在为 private 而不是 public
  • net.minecraft.client.gui.components
    • 大多数以 render*draw* 开头的方法已根据用法重命名为 extract*extract*RenderState
    • AbstractWidget#renderWidget -> extractWidgetRenderState
    • DebugScreenOverlay#render3dCrosshair 现在接受 CameraRenderState 而不是 Camera,以及 GUI 缩放 int
    • LogoRenderer#renderLogo -> extractRenderState
    • PlayerFaceRenderer -> PlayerFaceExtractor
      • draw -> extractRenderState
    • Renderable#render -> extractRenderState
    • StringWidget#clipText -> ComponentRenderUtils#clipText
    • TextCursorUtils#draw* -> extract*
  • net.minecraft.client.gui.components.debugchart
    • AbstractDebugChart
      • drawChart -> extractRenderState
      • drawDimensions -> extractSampleBars
      • drawMainDimension -> extractMainSampleBar
      • drawAdditionalDimensions -> extractAdditionalSampleBars
      • renderAdditionalLinesAndLabels -> extractAdditionalLinesAndLabels
      • drawStringWithShade -> extractStringWithShade
    • ProfilerPieChart#render -> extractRenderState
  • net.minecraft.client.gui.components.spectator.SpectatorGui#render* -> extract*
  • net.minecraft.client.gui.components.toasts
    • NowPlayingToast#renderToast -> extractToast
    • Toast#render -> extractRenderState
    • ToastManager, $ToastInstance#render -> extractRenderState
    • TutorialToast$Icons#render -> extractRenderState
  • net.minecraft.client.gui.contextualbar.ContextualBarRenderer
    • renderBackground -> extractBackground
    • render -> extractRenderState
    • renderExperienceLevel -> extractExperienceLevel
  • net.minecraft.client.gui.font
    • PlainTextRenderable#renderSprite 现在接受一个 Matrix4fc 而不是 Matrix4f 作为姿态
    • TextRenderable#render 现在接受一个 Matrix4fc 而不是 Matrix4f 作为姿态
  • net.minecraft.client.gui.render
    • DynamicAtlasAllocator - 一个用于处理动态大小纹理图集的分配器。
    • GuiItemAtlas - 一个用于用户界面中显示的所有物品的图集。
    • GuiRenderer#incrementFrameNumber -> endFrame,不是一对一
  • net.minecraft.client.gui.render.state.* -> .client.rendererer.state.gui.*
    • GuiItemRenderState 不再接受 String 名称
      • name 已移除
  • net.minecraft.client.gui.render.state.pip.* -> .client.rendererer.state.gui.pip.*
  • net.minecraft.client.gui.screens
    • LevelLoadingScreen#renderChunks -> extractChunksForRendering
    • Screen
      • renderWithTooltipAndSubtitles -> extractRenderStateWithTooltipAndSubtitles
      • renderBackground -> extractBackground
      • renderBlurredBackground -> extractBlurredBackground
      • renderPanorama -> extractPanorama
      • renderMenuBackground -> extractMenuBackground
      • renderMenuBackgroundTexture -> extractMenuBackgroundTexture
      • renderTransparentBackground -> extractTransparentBackground
  • net.minecraft.client.gui.screens.advancements
    • AdvancementTab#draw* -> extract*
    • AdvancementTabType
      • draw -> extractRenderState
      • drawIcon -> extractIcon
    • AdvancementWidget
      • draw -> extractRenderState
      • draw* -> extract*
  • net.minecraft.client.gui.screens.inventory
    • 大多数以 render*draw* 开头的方法已根据用法重命名为 extract*extract*RenderState
    • AbstractContainerScreen
      • renderContents -> extractContents
      • renderCarriedItem -> extractCarriedItem
      • renderSnapbackItem -> extractSnapbackItem
      • renderSlots -> extractSlots
      • renderTooltip -> extractTooltip
      • renderLabels -> extractLabels
      • renderBgScreen#extractBackground 取代
      • renderSlot -> extractSlot
    • AbstractMountInventoryScreen#drawSlot -> extractSlot
    • AbstractSignEditScreen#renderSignBackground -> extractSignBackground
    • CyclingSlotBackground#render -> extractRenderState
    • EffectsInInventory#render -> extractRenderState
    • InventoryScreen#renderEntityInInventoryFollowsMouse -> extractEntityInInventoryFollowsMouse
    • ItemCombinerScreen#renderErrorIcon -> extractErrorIcon
  • net.minecraft.client.gui.screens.inventory.tooltip
    • ClientTooltipComponent
      • renderText -> extractText
      • renderImage -> extractImage
    • TooltipRenderUtil#renderTooltipBackground -> extractTooltipBackground
  • net.minecraft.client.gui.screens.options
    • DifficultyButtons 现在是一个记录,接受 LayoutElement、用于难度的 CycleButtonLockIconButton 和当前 Level
      • create 现在接受 Level 并返回 DifficultyButtons 而不是 LayoutElement
      • refresh - 设置持有的按钮组件的数据。
    • HasDifficultyReaction - 一个响应难度更改的接口。
    • OptionsScreen 现在实现 HasDifficultyReaction
    • WorldOptionsScreen 现在实现 HasDifficultyReaction
      • 构造函数现在接受 Level
  • net.minecraft.client.gui.screens.recipebook
    • GhostSlots
      • render -> extractRenderState
      • renderTooltip -> extractTooltip
    • RecipeBookComponent#render* -> extract*
    • RecipeBookPage
      • render -> extractRenderState
      • renderTooltip -> extractTooltip
  • net.minecraft.cilent.gui.screens.reporting.ChatSelectionScreen$ChatSelectionList#renderItem -> extractItem
  • net.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen$GameRuleEntry#renderLabel -> extractLabel
  • net.minecraft.client.gui.spectator.SpectatorMenuItem#renderIcon -> extractIcon
  • net.minecraft.client.model.Model#renderType 现在有一个返回传入函数的重载
  • net.minecraft.client.model.object.book.BookModel$State 不再接受动画位置,并将开放的 float 移到第一个参数
    • forAnimation - 根据进度获取书本动画的当前状态。
  • net.minecraft.client.model.object.statue.CopperGolemStatueModel 现在使用 Unit 作为泛型而不是 Direction
  • net.minecraft.client.multiplayer.ClientLevel 现在实现 BlockAndTintGetter
    • update - 更新关卡的光照。
  • net.minecraft.client.multiplayer.chat.GuiMessageTag$Icon#draw -> extractRenderState
  • net.minecraft.client.particle
    • Particle#getLightColor -> getLightCoords
    • SimpleVerticalParticle - 一个垂直移动的粒子。
    • SingleQuadParticle$Layer
      • TERRAIN -> OPAQUE_TERRAIN, TRANSLUCENT_TERRAIN
      • ITEMS -> OPAQUE_ITEMS, TRANSLUCENT_ITEMS
      • bySprite - 从图集精灵获取层。
  • net.minecraft.client.renderer
    • CachedOrthoProjectionMatrixBuffer, CachedPerspectiveProjectionMatrixBuffer, PerspectiveProjectionMatrixBuffer -> ProjectionMatrixBuffer,有时带有 Projection,不是一对一
    • CloudRenderer 现在接受云范围 int
    • CubeMap 不再接受 Minecraft 实例
    • GameRenderer 现在接受 ModelManager 而不是 BlockRenderDispatcher
      • PROJECTION_Z_NEAR -> Camera#PROJECTION_Z_NEAR
      • setPanoramicScreenshotParameters, getPanoramicScreenshotParameters -> Camera#enablePanoramicMode, disablePanoramicMode; 不是一对一
      • isPanoramicMode -> Camera#isPanoramicMode
      • getProjectionMatrix -> Camera#getViewRotationProjectionMatrix,不是一对一
      • updateCamera -> Camera#update,不是一对一
      • getRenderDistance 已移除
      • cubeMap -> GuiRenderer#cubeMap,现在为 private 而不是 protected
      • getDarkenWorldAmount -> getBossOverlayWorldDarkening
      • lightTexture -> lightmap, levelLightmap; 不是一对一
      • getLevelRenderStategetGameRenderState 取代,返回 GameRenderState 而不是 LevelRenderState
      • pick -> Minecraft#pick,现在为 private 而不是 public
      • render 拆分为 updateextractrenderboolean 现在表示是否推进游戏时间而不是渲染关卡
    • GlobalSettingsUniform 现在接受 Vec3 相机位置而不是主 Camera 本身
    • ItemBlockRenderTypes 已移除
      • getChunkRenderTypegetMovingBlockRenderType 现在存储在 BakedQuad$SpriteInfo
      • getRenderLayer(FluidState) -> FluidModel#layer,不是一对一
      • setCutoutLeaves 已移除
        • 这应直接从选项中获取
    • MultiblockChestResources - 一个包含基于 ChestType 的一些数据的记录。
    • LevelRenderer 现在接受 GameRenderState 而不是 LevelRenderState
      • update - 更新关卡。
      • renderLevel 现在接受 CameraRenderState 而不是 Camera,一个 Matrix4fc 而不是 Matrix4f 用于模型视图,以及 ChunkSectionsToRender;不再接受用于投影矩阵的 Matrix3f
      • extractLevel - 提取关卡状态。
      • prepareChunkRenders 现在是 public 而不是 private
      • captureFrustum, killFrustum, getCapturedFrustum 已移除
      • getLightColor -> getLightCoords,现在接受 BlockAndLightGetter 而不是 BlockAndTintGetter
      • $BrightnessGetter#packedBrightness 现在接受 BlockAndLightGetter 而不是 BlockAndTintGetter
    • LightTexture -> Lightmap
      • tick -> LightmapRenderStateExtractor#tick
      • updateLightTexture -> render
      • pack -> LightCoordsUtil#pack
      • block -> LightCoordsUtil#block
      • sky -> LightCoordsUtil#sky
      • lightCoordsWithEmission -> LightCoordsUtil#lightCoordsWithEmission
    • MaterialMapper -> SpriteMapper
    • OrderedSubmitNodeCollector
      • submitBlock 已移除
      • submitBlockModel 现在接受一个 BlockStateModelPart 列表而不是 BlockStateModel,以及一个 int 数组(色调颜色数组)而不是三个 float 用于单一颜色
      • submitItem 不再接受 RenderType
      • submitModel 现在有接受纹理的 Identifier 或带有 SpriteGetterSpriteId 以及一个 int 色调颜色的重载
      • submitBreakingBlockModel - 提交方块破坏覆盖层。
    • PanoramaRendererPanorama 取代
      • registerTextures -> GuiRenderer#registerPanoramaTextures
      • render -> extractRenderState
    • PanoramicScreenshotParameters 记录已移除
    • PostChain 现在接受一个 ProjectionProjectionMatrixBuffer 而不是 CachedOrthoProjectionMatrixBuffer
      • load 现在接受一个 ProjectionProjectionMatrixBuffer 而不是 CachedOrthoProjectionMatrixBuffer
    • RenderPipelines
      • ENTITY_CUTOUT_NO_CULL -> ENTITY_CUTOUT
        • 原来的带剔除的 cutout 被 ENTITY_CUTOUT_CULL 取代
      • ENTITY_CUTOUT_NO_CULL_Z_OFFSET -> ENTITY_CUTOUT_Z_OFFSET
      • ENTITY_SMOOTH_CUTOUT -> END_CRYSTAL_BEAM
      • ENTITY_NO_OUTLINEENTITY_TRANSLUCENT 取代,渲染类型构造时 affects outline 为 false
      • ENTITY_DECAL, DRAGON_EXPLOSION_ALPHA -> ENTITY_CUTOUT_DISSOLVE,不是一对一
      • ITEM_ENTITY_TRANSLUCENT_CULL -> ENTITY_TRANSLUCENT_CULL, ITEM_CUTOUT, ITEM_TRANSLUCENT; 不是一对一
      • TRANSLUCENT_MOVING_BLOCKTRANSLUCENT_BLOCK 取代
      • BANNER_PATTERN - 用于渲染旗帜图案的管线。
    • ScreenEffectRenderer#renderScreenEffect 现在接受 boolean 表示玩家是否处于第一人称以及是否隐藏 GUI
    • Sheets
      • *CHEST_*LOCATION* 已根据资源用途合并到 CHEST_* 字段之一
      • translucentBlockSheet - 使用方块图集的可剔除实体物品半透明渲染类型。
      • cutoutBlockItemSheet - 使用方块图集的物品 cutout 渲染类型。
      • bannerSheet -> RenderTypes#entityTranslucent,不是一对一
      • cutoutItemSheet - 使用物品图集的物品 cutout 渲染类型。
      • get*Material -> get*Sprite
      • chooseMaterial -> chooseSprite
    • SpecialBlockModelRendererBuiltInBlockModels 取代,不是一对一
      • renderByBlock -> BlockModelRenderState#submit*,不是一对一
    • SubmitNodeCollection
      • getBlockSubmits 已移除
      • getBreakingBlockModelSubmits - 获取已提交的方块破坏覆盖层。
    • SubmitNodeCollector$ParticleGroupRenderer
      • isEmpty - 此组中是否没有要渲染的粒子。
      • prepare 现在接受是否为半透明层准备粒子
      • render 不再接受半透明 boolean
    • SubmitNodeStorage
      • $BlockModelSubmit 现在接受一个 BlockStateModelPart 列表而不是 BlockStateModel,以及一个 int 数组(色调颜色数组)而不是三个 float 用于单一颜色
      • $BlockSubmit 已移除
      • $BreakingBlockModelSubmit - 一个包含渲染方块破坏覆盖层信息的记录。
      • $ItemSubmit 不再接受 RenderType
      • $MovingBlockSubmit, $NameTagSubmit, $ShadowSubmit, $TextSubmit 现在接受一个 Matrix4fc 而不是 Matrix4f 作为姿态
    • VirtualScreenGpuBackend 取代
  • net.minecraft.client.renderer.block
    • BlockAndTintGetter - 一个用于位置方块着色(例如生物群系)的获取器。
    • BlockModelRenderState - 方块模型的渲染状态。
    • BlockModelResolver - 一个用于设置 BlockState 渲染状态的辅助类。
    • BlockModelSet - 持有与每个 BlockState 关联的 BlockModel
    • BlockModelShaper -> BlockStateModelSet,不是一对一
      • getParticleIcon -> getParticleMaterial,现在返回 Material$Baked 而不是 TextureAtlasSprite
      • getBlockModel -> get
      • getModelManager, replaceCache 已移除
    • BlockQuadOutput - 一个用于将烘焙四边形信息写入某些输出(如缓冲区)的函数接口。
    • BlockRenderDispatcher 类已移除
      • getBlockModelShaper -> getModelSet,不是一对一
      • renderBreakingTextureSubmitNodeCollector#submitBreakingBlockModel 取代
      • renderBatched 被直接调用 ModelBlockRenderer#tesselateBlock 取代
      • renderLiquid 被直接调用 FluidRenderer#tesselate 取代
      • renderSingleBlock 现在内联在 BlockFeatureRenderer#renderBlockModelSubmits 中,一个 private 方法
        • 使用 ModelBlockRenderer#tesselateBlock 作为替代
    • FluidModel - 持有渲染器数据的基础流体模型。
    • FluidStateModelSet - 持有与每个 Fluid 关联的 FluidModel
    • LoadedBlockModels - 一个为每个 BlockState 烘焙 BlockModel 的任务。
    • LiquidBlockRenderer -> FluidRenderer,不是一对一
      • 构造函数现在接受 FluidStateModelSet 而不是 SpriteGetter
      • tesselate 现在接受一个 FluidRenderer$Output 而不是 VertexConsumer
      • $Output - 获取用于 ChunkSectionLayerVertexConsumer
    • ModelBlockRenderer 现在接受 boolean 用于环境光遮蔽和剔除
      • tesselateBlock 现在接受一个 BlockQuadOutput 而不是 VertexConsumer,XYZ float 而不是 PoseStackBlockStateModel 而不是 BlockModelPart 列表,不再接受剔除 booleanint 覆盖,并接受种子 long
      • tesselateWithAO -> tesselateAmbientOcclusion,现在是 private 而不是 public
      • tesselateWithoutAO -> tesselateFlat,现在是 private 而不是 public
      • renderModel 现在内联在 BlockFeatureRenderer#renderBlockModelSubmits 中,一个 private 方法
      • forceOpaque - 方块纹理是否应为不透明而不是半透明。
      • enableCaching -> BlockModelLighter$Cache#enable
      • clearCache -> BlockModelLighter$Cache#disable
      • $AdjacencyInfo -> BlockModelLighter$AdjacencyInfo,现在是 private 而不是 protected
      • $AmbientOcclusionRenderStorageBlockModelLighter 取代,不是一对一
      • $AmbientVertexRemap -> BlockModelLighter$AmbientVertexRemap
      • $Cache -> BlockModelLighter$Cache
      • $CommonRenderStorageBlockModelLighter 取代,不是一对一
      • $SizeInfo -> BlockModelLighter$SizeInfo
    • MovingBlockRenderState#level -> cardinalLighting, lightEngine; 不是一对一
    • SelectBlockModel - 一个由其解析属性确定或选择的方块模型。
  • net.minecraft.client.renderer.block.model
    • BakedQuad -> .client.resources.model.geometry.BakedQuad
      • 构造函数现在接受一个 $MaterialInfo 而不是 TextureAtlasSpriteint 色调索引、int 光发射和 boolean 阴影
      • FLAG_TRANSLUCENT - 一个标志,标记烘焙四边形具有半透明性。
      • FLAG_ANIMATED - 一个标志,标记烘焙四边形具有动画纹理。
      • isTinted -> $MaterialInfo#isTinted
      • $MaterialFlags - 一个注解,标记给定的整数是否定义材质的标志。
      • $MaterialInfo - 一个持有如何渲染四边形信息的记录。
    • BlockDisplayContext - 一个表示方块显示上下文的对象。
    • BlockElement -> .client.resources.model.cuboid.CuboidModelElement
    • BlockElementFace -> .client.resources.model.cuboid.CuboidFace
    • BlockElementRotation -> .client.resources.model.cuboid.CuboidRotation
    • BlockModel - 基础方块模型,用于在世界上下文之外更新渲染状态。
      • 原始实现已移至 .client.resources.model.cuboid.CuboidModel
    • BlockModelDefinition -> .block.dispatch.BlockStateModelDispatcher
    • BlockModelPart -> .block.dispatch.BlockStateModelPart
      • particleIcon -> particleMaterial,现在返回 Material$Baked 而不是 TextureAtlasSprite
      • materialFlags - 处理模型使用的材质的标志。
    • BlockStateModel -> .block.dispatch.BlockStateModel
      • particleIcon -> particleMaterial,现在返回 Material$Baked 而不是 TextureAtlasSprite
      • materialFlags, hasMaterialFlag - 处理模型使用的材质的标志。
    • BlockStateModelWrapper - 包含模型、色调和变换的基础方块模型。
    • CompositeBlockModel - 将多个方块模型叠加在一起。
    • ConditionalBlockModel - 一个根据从某个属性获取的布尔值显示不同模型的方块模型。
    • EmptyBlockModel - 不显示任何内容的方块模型。
    • FaceBakery -> .client.resources.model.cuboid.FaceBakery
      • bakeQuad 重载现在接受一个 ModelBaker 而不是 ModelBaker$PartCache,以及一个 Material$Baked 而不是 TextureAtlasSprite
        • 它还有一个接受 BlockElementFace 字段而不是对象本身的重载
      • 另一个 bakedQuad 重载现在接受 BakedQuad$MaterialInfo 而不是 int 色调索引和光发射,以及阴影 boolean
    • ItemModelGenerator -> .client.resources.model.cuboid.ItemModelGenerator
    • ItemTransform -> .client.resources.model.cuboid.ItemTransform
    • ItemTransforms -> .client.resources.model.cuboid.ItemTransforms
    • SimpleModelWrapper -> .client.resources.model.SimpleModelWrapper
      • 构造函数现在接受一个 Material$Baked 而不是 TextureAtlasSprite 作为粒子
    • SimpleUnbakedGeometry -> .client.resources.model.cuboid.UnbakedCuboidGeometry
    • SingleVariant -> .block.dispatch.SingleVariant
    • SpecialBlockModelWrapper - 一个用于通过 SpecialModelRenderer 提交其元素的方块模型。
    • TextureSlots -> .client.resources.model.sprite.TextureSlots
    • Variant -> .block.dispatch.Variant
    • VariantMutator -> .block.dispatch.VariantMutator
    • VariantSelector -> .block.dispatch.VariantSelector
  • net.minecraft.client.renderer.block.model.multipart.* -> .block.dispatch.multipart.*
  • net.minecraft.client.renderer.block.model.properties.conditional
    • ConditionalBlockModelProperty - 一个从 BlockState 计算某个 boolean 的属性。
    • IsXmas - 返回当前时间是否在 12 月 24 日至 26 日之间。
  • net.minecraft.client.renderer.block.model.properties.select
    • DisplayContext - 基于当前 BlockDisplayContext 的情况。
    • SelectBlockModelProperty - 一个从 BlockState 计算某个开关状态的属性。
  • net.minecraft.client.renderer.blockentity
    • AbstractEndPortalRenderer
      • renderCube -> submitCube,现在为 protectedstatic 而不是 private
      • submitSpecial - 提交末地传送门立方体,由特殊渲染器使用。
      • getExtents - 获取每个面的顶点。
      • getOffsetUp, getOffsetDown 已移除
      • renderType 已移除
    • AbstractSignRenderer 现在接受一个泛型用于 SignRenderState
      • getSignModel 现在接受 SignRenderState 泛型而不是 BlockStateWoodType
      • getSignModelRenderScale, getSignTextRenderScale, getTextOffset, translateSignSignRenderState#transformationsSignRenderState$SignTransformations 取代
      • getSignMaterial -> getSignSprite
    • BannerRenderer
      • TRANSFORMATIONS - 当在墙上或地上时要应用的变换。
      • submitPatterns 不再接受基础 SpriteId、图案是否有箔以及轮廓颜色
      • submitSpecial 现在接受 BannerBlock$AttachmentType
    • BedRenderer
      • submitSpecial 已移除
        • 这被调用两次 submitPiece 或通过 BedSpecialRenderer 为每个床部件制作组合体所取代
      • submitPiece 现在是 public 而不是 private,接受 BedPart 而不是 Model$SimpleDirection 或是否在 Z 方向平移的 boolean
      • getExtents 现在接受 BedPart
      • modelTransform - 获取给定 Direction 的变换。
    • BlockEntityRenderDispatcher 现在接受 BlockModelResolver 而不是 BlockRenderDispatcher,并且不再接受 ItemRenderer
      • prepare 现在接受一个 Vec3 相机位置而不是 Camera 本身
    • BlockEntityRendererProvider$Context 现在接受 BlockModelResolver 而不是 BlockRenderDispatcher,并且不再接受 ItemRenderer
      • materials -> sprites
    • ChestRenderer
      • LAYERS - 持有箱子的模型层。
      • modelTransformation - 获取给定 Direction 的变换。
    • ConduitRenderer#DEFAULT_TRANSFORMATION - 要应用的默认变换。
    • CopperGolemStatueBlockRenderer#modelTransformation - 获取给定 Direction 的变换。
    • DecoratedPotRenderer#modelTransformation - 获取给定 Direction 的变换。
    • HangingSignRenderer 现在使用 HangingSignRenderState
      • MODEL_RENDER_SCALE 现在是 private 而不是 public
      • TRANSFORMATIONS - 当在墙上或地上时要应用的变换。
      • translateBase -> baseTransformation,现在是 private 而不是 public
      • $AttachmentType -> HangingSignBlock$Attachment
        • byBlockState -> $Models#get
      • $ModelKey 记录已移除
    • ShulkerBoxRenderer
      • modelTransform - 获取给定 Direction 的变换。
      • getExtents 不再接受 Direction
    • SignRenderer -> StandingSignRenderer
      • TRANSFORMATIONS - 当在墙上或地上时要应用的变换。
      • createSignModel 现在接受一个 PlainSignBlock$Attachment 而不是一个表示方块是否站立的 boolean
    • SkullBlockRenderer
      • TRANSFORMATIONS - 当在墙上或地上时要应用的变换。
      • submitSkull 不再接受 Directionfloat 旋转
    • WallAndGroundTransformations - 一个持有 Direction 到墙上变换映射的类,以及一个计算地面变换的 int 函数,其中 int 段通常表示旋转状态的数量。
  • net.minecraft.client.renderer.blockentity.state
    • BannerRenderState
      • angle -> transformation,不是一对一
      • standing -> attachmentType,不是一对一
    • BedRenderState#isHead -> part,不是一对一
    • BlockEntityRenderState#blockState 现在是 private 而不是 public
    • ChestRenderState#angle -> facing,不是一对一
    • CondiutRenderState -> ConduitRenderState
    • CopperGolemStatueRenderState#oxidationState - 当前的氧化状态。
    • HangingSignRenderState - 悬挂标志的渲染状态。
    • ShelfRenderState#facing - 架子面向的方向。
    • SignRenderState#woodType - 标志的木材类型。
    • SkullblockRenderState#direction, rotationDegrees -> transformation,不是一对一
    • StandingSignRenderState - 站立标志的渲染状态。
  • net.minecraft.client.renderer.chunk
    • ChunkSectionLayer 现在接受一个 boolean 表示层是否为半透明,而不是仅在上传时排序
      • byTransparency - 根据其透明度设置获取层。
      • sortOnUpload -> translucent,不是一对一
      • vertexFormat - 层使用的管线的顶点格式。
    • ChunkSectionsToRender#drawsPerLayer -> drawGroupsPerLayer,其值为 int 到绘图列表的映射
    • CompiledSectionMesh
      • uploadMeshLayerisVertexBufferUploadedsetVertexBufferUploaded 取代
      • uploadLayerIndexBufferisIndexBufferUploadedsetIndexBufferUploaded 取代
    • RenderRegionCache#createRegion 现在接受 ClientLevel 而不是 Level
    • SectionBuffers -> SectionRenderDispatcher$RenderSectionBufferSlice,不是一对一
    • SectionCompiler 现在接受 boolean 用于环境光遮蔽和 cutout 树叶、BlockStateModelSetFluidStateModelSetBlockColors 而不是 BlockRenderDispatcher
    • SectionMesh
      • getBuffers -> getSectionDraw,不是一对一
      • $SectionDraw - 部分的绘图信息。
    • SectionRenderDispatcher 现在接受 SectionCompiler 而不是 BlockRenderDispatcherBlockEntityRenderDispatcher
      • getRenderSectionSlice - 获取要为块层渲染的部分网格的缓冲区切片。
      • uploadAllPendingUploads -> uploadGlobalGeomBuffersToGPU,不是一对一
      • lock, unlock - 处理在将数据从一个位置复制到另一个位置时锁定调度程序,通常用于 GPU 分配。
      • getToUpload 已移除
      • setLevel 现在接受 SectionCompiler
      • $RenderSection
        • upload, uploadSectionIndexBuffer -> addSectionBuffersToUberBuffer,现在是 private
        • $CompileTask
          • doTask 现在返回一个 $SectionTaskResult 而不是 CompletableFuture
      • $SectionTaskResult -> $RenderSection$CompileTask$SectionTaskResult
  • net.minecraft.client.renderer.culling.Frustum 现在接受一个 Matrix4fc 而不是 Matrix4f 用于模型视图
    • set - 从另一个视景体复制信息。
  • net.minecraft.client.renderer.entity
    • AbstractBoatRenderer 现在接受 Identifier 纹理
      • renderType 已移除
    • AbstractMinecartRenderer
      • BLOCK_DISPLAY_CONTEXT - 显示矿车内方块的上下文。
      • submitMinecartContents 现在接受一个 BlockModelRenderState 而不是 BlockState
    • CopperGolemRenderer#BLOCK_DISPLAY_CONTEXT - 显示天线方块的上下文。
    • DisplayRenderer
      • BLOCK_DISPLAY_CONTEXT - 显示所显示方块的上下文。
      • blockModelResolver - 方块模型解析器。
    • EndermanRenderer#BLOCK_DISPLAY_CONTEXT - 显示手持方块的上下文。
    • EntityRenderDispatcher 现在接受 BlockModelResolver 而不是 BlockRenderDispatcher
    • EntityRenderer#submitNameTag -> submitNameDisplay,现在可选地接受 Y 位置 int 作为名称标签附件的偏移量
    • EntityRendererProvider$Context 现在接受 BlockModelResolver 而不是 BlockRenderDispatcher
      • getMaterials -> getSprites
      • getBlockRenderDispatchergetBlockModelResolver 取代
    • IronGolemRenderer#BLOCK_DISPLAY_CONTEXT - 显示手持方块的上下文。
    • ItemFrameRenderer#BLOCK_DISPLAY_CONTEXT - 显示所显示方块的上下文。
    • ItemRenderer 类已移除
      • 使用 ItemStackRenderState 将元素提交给功能调度程序
      • ENCHANTED_GLINT_ARMOR -> ItemFeatureRenderer#ENCHANTED_GLINT_ARMOR
      • ENCHANTED_GLINT_ITEM -> ItemFeatureRenderer#ENCHANTED_GLINT_ITEM
      • NO_TINT -> ItemFeatureRenderer#NO_TINT
      • getFoilBuffer -> ItemFeatureRenderer#getFoilBuffer
      • getFoilRenderType -> ItemFeatureRenderer#getFoilRenderType,现在是 public 而不是 private
    • MushroomCowRenderer#BLOCK_DISPLAY_CONTEXT - 显示附加方块的上下文。
    • SnowGolemRenderer#BLOCK_DISPLAY_CONTEXT - 显示头部方块的上下文。
    • TntRenderer#BLOCK_DISPLAY_CONTEXT - 显示 TNT 方块的上下文。
    • TntMinecartRenderer#submitWhiteSolidBlock 现在接受一个 BlockModelRenderState 而不是 BlockState
  • net.minecraft.client.renderer.entity.layers
    • BlockDecorationLayer 现在接受一个返回 BlockModelRenderState 的函数而不是可选的 BlockState
    • MushroomCowMushroomLayer 不再接受 BlockRenderDispatcher
    • SnowGolemHeadLayer 不再接受 BlockRenderDispatcher
  • net.minecraft.client.renderer.entity.state
    • AvatarRenderState#scoreText -> EntityRenderState#scoreText
    • BlockDisplayEntityRenderState#blockRenderState -> blockModel,现在是 BlockModelRenderState 而不是 BlockRenderState
    • CopperGolemRenderState#blockOnAntenna 现在是 BlockModelRenderState 而不是可选的 BlockState
    • EndermanRenderState#carriedBlock 现在是 BlockModelRenderState 而不是可空的 BlockState
    • IronGolemRenderState#flowerBlock - 铁傀儡手持的花。
    • ItemFrameRenderState#frameModel - 物品框方块的模型。
    • MinecartRenderState#displayBlockState -> displayBlockModel,现在是 BlockModelRenderState 而不是 BlockState
    • MushroomCowRenderState#mushroomModel - 附着在牛上的蘑菇模型。
    • SnowGolemRenderState#hasPumpkin -> headBlock,现在是 BlockModelRenderState 而不是 boolean
    • TntRenderState#blockState 现在是 BlockModelRenderState 而不是可空的 BlockState
  • net.minecraft.client.renderer.features
    • 功能 render 方法已拆分为 renderSolid(用于不透明渲染类型)和 renderTranslucent(用于半透明渲染类型)
    • 一些 render* 方法现在接受 OptionsRenderState
    • BlockFeatureRenderer
      • renderSolid 现在接受 BlockStateModelSet 而不是 BlockRenderDispatcher
      • renderTranslucent 现在接受 BlockStateModelSet 和 crumbling MultiBufferSource$BufferSource 而不是 BlockRenderDispatcher
    • FeatureRenderDispatcher 现在接受 GameRenderStateModelManager
      • renderAllFeatures 已拆分为 renderSolidFeaturesrenderTranslucentFeatures
        • 原始方法现在调用这两个方法,先 solid 后 translucent
      • clearSubmitNodes - 清除提交节点存储。
      • renderTranslucentParticles - 渲染收集的半透明粒子。
    • FlameFeatureRenderer#render -> renderSolid
    • LeashFeatureRenderer#render -> renderSolid
    • NameTagFeatureRenderer#render -> renderTranslucent
    • ShadowFeatureRenderer#render -> renderTranslucent
    • TextFeatureRenderer#render -> renderTranslucent
  • net.minecraft.client.renderer.fog
    • FogData#color - 雾的颜色。
    • FogRenderer
      • setupFog 现在返回一个 FogData 而不是 Vector4f 雾颜色
      • updateBuffer - 用雾数据更新缓冲区。
  • net.minecraft.client.renderer.gizmos.DrawableGizmoPrimitives#render 现在接受一个 Matrix4fc 而不是 Matrix4f 用于模型视图
  • net.minecraft.client.renderer.item
    • BlockModelWrapper -> CuboidItemModelWrapper
      • 构造函数不再接受 RenderType 函数,现在接受 Matrix4fc 变换
      • $Unbaked 现在接受一个可选的 Transformation
    • CompositeModel$Unbaked 现在接受一个可选的 Transformation
    • ConiditionalItemModel$Unbaked 现在接受一个可选的 Transformation
    • ItemModel
      • $BakingContext
        • materials -> sprites
        • missingItem - 获取带有给定 Matrix4fc 变换的缺失物品模型。
      • $Unbaked#bake 现在接受来自任何父客户端物品的 Matrix4fc 变换
    • ItemStackRenderState
      • pickParticleIcon -> pickParticleMaterial,现在返回 Material$Baked 而不是 TextureAtlasSprite
      • $LayerRenderState
        • EMPTY_TINTS - 一个表示不应用色调的 int 数组。
        • setRenderType 已移除
        • setParticleIcon -> setParticleMaterial,现在接受 Material$Baked 而不是 TextureAtlasSprite
        • setTransform -> setItemTransform
        • setLocalTransform - 设置客户端物品变换,该变换在物品显示变换后应用。
        • prepareTintLayers -> tintLayers,不是一对一
    • MissingItemModel#withTransform - 获取带有给定变换的缺失物品模型。
    • ModelRenderProperties#particleIcon -> particleMaterial,现在接受 Material$Baked 而不是 TextureAtlasSprite
    • RangeSelectItemModel$Unbaked 现在接受一个可选的 Transformation
    • SelectItemModel
      • $ModelSelector#get 不再支持可空的 ItemModel
      • $Unbaked 现在接受一个可选的 Transformation
      • $UnbakedSwitch#bake 现在接受 Matrix4fc 变换
    • SpecialModelWrapper 现在接受 Matrix4fc 变换
      • $Unbaked 现在接受一个可选的 Transformation
  • net.minecraft.client.renderer.rendertype
    • RenderType#outputTarget - 获取输出目标。
    • RenderTypes
      • MOVING_BLOCK_SAMPLERcreateMovingBlockSetup 取代,现在是 private
      • entityCutoutNoCull -> entityCutout
        • 原来的带剔除的 cutout 被 entityCutoutCull 取代
      • entityCutoutNoCullZOffset -> entityCutoutZOffset
      • entitySmoothCutout -> endCrystalBeam
      • entityNoOutline -> entityTranslucentaffectsOutlinefalse
      • entityDecal, dragonExplosionAlpha -> entityCutoutDissolve,不是一对一
      • itemEntityTranslucentCull -> entityTranslucentCullItemTarget, itemCutout, itemTranslucent; 不是一对一
      • bannerPattern - 用于渲染旗帜图案的渲染类型。
  • net.minecraft.client.renderer.special
    • BannerSpecialRenderer, $Unbaked 现在接受 BannerBlock$AttachmentType
      • $Unbaked 现在使用 BannerPatternLayers 作为泛型
    • BedSpecialRenderer, $Unbaked 现在接受 BedPart
      • $Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
    • BellSpecialRenderer - 钟的特殊渲染器。
    • BookSpecialRenderer - 附魔台上书的特殊渲染器。
    • ChestSpecialRenderer$Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
      • 构造函数现在接受 ChestType
      • *_CHEST_TEXTURE 已从字段名中移除,现在是 MultiBlockChestResources
      • ENDER_CHEST_TEXTURE -> ENDER_CHEST
    • ConduitSpecialRenderer$Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
    • CopperGolemStatueSpecialRenderer$Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
    • DecoratedPotSpecialRenderer$Unbaked 现在使用 PotDecorations 作为泛型
    • EndCubeSpecialRenderer - 末地传送门立方体的特殊渲染器。
    • HangingSignSpecialRenderer$Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
      • 构造函数现在接受 HangingSignBlock$Attachment
    • NoDataSpecialModelRenderer
      • submit 不再接受 ItemDisplayContext
      • $Unbaked - 不需要提取数据的特殊模型渲染器的未烘焙渲染器。
    • PlayerHeadSpecialRenderer$Unbaked 现在使用 PlayerSkinRenderCache$RenderInfo 作为泛型
    • ShieldSpecialRenderer
      • DEFAULT_TRANSFORMATION - 要应用的默认变换。
      • $Unbaked 现在使用 DataComponentMap 作为泛型
    • ShulkerBoxSpecialRenderer, $Unbaked 不再接受 Direction 方向
      • $Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
    • SkullSpecialRenderer$Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
    • SpecialModelRenderer
      • submit 不再接受 ItemDisplayContext
      • $BakingContext
        • materials -> sprites
        • $SimpleBlockModel$BakingContextItemModel$BakingContext 取代
          • materials -> sprites
      • $Unbaked 现在具有从表示对象中提取参数的泛型
    • SpecialModelRenderers#createBlockRenderers -> BuiltInBlockModels#createBlockModels,不是一对一
    • StandingSignSpecialRenderer$Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
      • 构造函数现在接受 PlainSignBlock$Attachment
    • TridentSpecialRenderer
      • DEFAULT_TRANSFORMATION - 要应用的默认变换。
      • $Unbaked 现在实现 NoDataSpecialModelRenderer$Unbaked
  • net.minecraft.client.renderer.state.* -> .state.level.*
  • net.minecraft.client.renderer.state
    • GameRenderState - 游戏的渲染状态。
    • OptionsRenderState - 客户端用户选项的渲染状态。
    • WindowRenderState - 游戏窗口的渲染状态。
  • net.minecraft.client.renderer.state.gui.GuiRenderState#submit* 方法已重命名为 add*
  • net.minecraft.client.renderer.state.level
    • BlockBreakingRenderState 现在是一个记录,不再扩展 MovingBlockRenderState
      • 构造函数接受 BlockPosBlockState 和当前进度 int
    • CameraEntityRenderState - 相机实体的渲染状态。
    • CameraRenderState
      • xRot, yRot - 相机的旋转。
      • entityPos 已移除
      • isPanoramicMode - 相机是否处于全景模式。
      • cullFrustum - 剔除视景体。
      • fogType, fogData - 雾元数据。
      • hudFov - HUD 视场角。
      • depthFar - 深度 Z 远平面。
      • projectionMatrix, viewRotationMatrix - 用于从世界空间转换到屏幕空间的矩阵。
      • entityRenderState - 相机附加到的实体。
    • LevelRenderState
      • lastEntityRenderStateCount - 渲染到屏幕的实体数量。
      • cloudColor, cloudHeight - 云元数据。
    • LightmapRenderState - 光照图的渲染状态。
  • net.minecraft.client.renderer.texture
    • MipmapGenerator#generateMipLevels 现在接受计算出的图像 Transparency
    • SpriteContents
      • transparency - 获取精灵的透明度。
      • getUniqueFrames 现在返回一个 IntList 而不是 IntStream
      • computeTransparency - 计算选定 UV 边界的透明度。
      • $AnimatedTexture#getUniqueFrames 现在返回一个 IntList 而不是 IntStream
    • TextureAtlasSprite#transparency - 获取精灵的透明度。
  • net.minecraft.client.resources.model
    • AtlasManager -> .model.sprite.AtlasManager
    • BlockModelRotation -> .client.renderer.block.dispatch.BlockModelRotation
    • Material -> .model.sprite.SpriteId,不是一对一
    • MaterialSet -> .model.sprite.SpriteGetter
    • MissingBlockModel -> .model.cuboid.MissingCuboidModel
    • ModelBaker
      • sprites -> materials
      • parts -> interner
      • $PartCache -> $Interner
        • vector(float, float, float) 已移除
        • materialInfo - 获取内部化的材质信息对象。
    • ModelBakery
      • BANNER_BASE -> Sheets#BANNER_BASE
      • SHIELD_BASE -> Sheets#SHIELD_BASE
      • NO_PATTERN_SHIELD -> Sheets#SHIELD_BASE_NO_PATTERN
      • LAVA_* -> FluidStateModelSet#LAVA_MODEL,现在是 private 而不是 public
      • WATER_* -> FluidStateModelSet#WATER_MODEL,现在是 private 而不是 public
      • $BakingResult#getBlockStateModel - 从 BlockState 获取 BlockStateModel
      • $MissingModels 现在接受一个 MissingItemModel 而不是 ItemModel 用于 Item,以及一个 FluidModel
    • ModelManager
      • BLOCK_OR_ITEM 已移除
      • getMissingBlockStateModel -> BlockStateModelSet#missingModel
      • getBlockModelShaper -> getBlockStateModelSet,不是一对一
      • getBlockModelSet - 获取 BlockState 到方块模型的映射。
      • specialBlockModelRenderer 已移除
      • getFluidStateModelSet - 获取 Fluid 到流体模型的映射。
    • ModelState -> .client.renderer.block.dispatch.ModelState
    • QuadCollection -> .model.geometry.QuadCollection
      • addAll - 添加另一个四边形集合中的所有元素。
      • materialFlags, hasMaterialFlag - 处理模型使用的材质的标志。
    • ResolvedModel#resolveParticleSprite -> resolveParticleMaterial,现在返回 Material$Baked 而不是 TextureAtlasSprite
    • SpriteGetter -> .model.sprite.MaterialBaker
    • UnbakedGeometry -> .model.geometry.UnbakedGeometry
    • WeightedVariants -> .client.renderer.block.dispatch.WeightedVariants
  • net.minecraft.client.resources.model.sprite.Material - 对纹理精灵的引用,以及是否强制纹理半透明。
  • net.minecraft.world.entity.animal.Animal#isBrightEnoughToSpawn 现在接受一个 BlockAndLightGetter 而不是 BlockAndTintGetter
  • net.minecraft.world.level
    • BlockAndTintGetter -> BlockAndLightGetter
      • BlockAndTintGetter 现在是客户端专用的,实现 BlockAndLightGetter
      • getShade -> cardinalLighting;不是一对一
      • getBlockTint -> BlockAndTintGetter#getBlockTint
    • CardinalLighting - 持有每个方向应用的光照。
    • EmptyBlockAndTintGetter -> BlockAndTintGetter#EMPTY
    • LevelReader 现在实现 BlockAndLightGetter 而不是 BlockAndTintGetter
  • net.minecraft.world.level.block
    • BannerBlock$AttachmentType - 旗帜附着到另一个方块的位置。
    • CeilingHangingSignBlock 现在实现 HangingSignBlock
      • getAttachmentPoint - 获取标志附着到另一个方块的位置。
    • HangingSignBlock - 一个定义附着到另一个方块的悬挂标志的接口。
    • PlainSignBlock - 一个定义附着到另一个方块的普通标志的接口。
    • StandingSignBlock 现在实现 PlainSignBlock
    • WallingHangingSignBlock 现在实现 HangingSignBlock
    • WallSignBlock 现在实现 PlainSignBlock
  • net.minecraft.world.level.block.state.BlockBehaviour#getLightBlock, $BlockStateBase#getLightBlock -> getLightDampening
  • net.minecraft.world.level.block.state.properties
    • BedPart#CODEC - 床部分的编解码器。
    • ChestType#CODEC - 箱子类型的编解码器。
  • net.minecraft.world.level.dimension.DimensionType$CardinalLightType -> CardinalLighting$Type

次要迁移

以下是有用或有趣的添加、更改和删除列表,这些内容在入门指南中不值得单独列出一个章节。

可种植标签

用于确定可种植植物能否存活或被放置的方块已移至方块和流体标签。每个此类标签以 support_* 开头,后跟方块(例如 bamboocactus)或组(例如 cropsdry_vegetation)。这由相关的方块子类通过重写 Block#canSurvive 或对于植被 VegetationBlock#mayPlaceOn 来处理。

  • net.minecraft.world.level.block
    • AttachedStemBlock 现在接受一个 TagKey 表示它可以放置在上面的方块
    • FarmBlock -> FarmlandBlock
    • FungusBlock -> NetherFungusBlock,不是一对一
    • RootsBlock -> NetherRootsBlock,不是一对一
    • WaterlilyBlock -> LilyPadBlock,不是一对一
    • StemBlock 现在接受一个 TagKey 表示它可以放置在上面的方块,以及一个 TagKey 表示其果实可以放置在上面的方块

容器屏幕变更

AbstractContainerScreen 的使用略有变化,需要一些小的更改。首先,imageWidthimageHeight 现在是 final 的,可以在构造函数中作为参数设置。如果未指定这两个参数,它们默认为原始的 176 x 166 背景图像。

// 假设存在某个 AbstractContainerMenu 子类
public class ExampleContainerScreen extends AbstractContainerScreen<ExampleContainerMenu> {

    // 构造函数
    public ExampleContainerScreen(ExampleContainerMenu menu, Inventory playerInventory, Component title) {
        // 在构造函数的最后两个参数中指定图像宽度和高度
        super(menu, playerInventory, title, 256, 256);
    }
}

此外,AbstractContainerScreen#render 的重写现在在调用栈末尾调用 renderTooltip。这意味着,在大多数情况下,你不应该在 AbstractContainerScreen 的子类型中重写 render。所有事情都可以通过类提供的其他方法之一完成。

  • net.minecraft.client.gui.screens.inventory.AbstractContainerScreen 现在可选地接受背景图像宽度和高度
    • imageWidth, imageHeight 现在是 final 的
    • DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT - 容器背景图像的默认宽度和高度。
    • slotClicked 现在接受一个 ContainerInput 而不是 ClickType
    • render 重写现在默认调用 renderTooltip
  • net.minecraft.world.inventory
    • AbstractContainerMenu#clicked 现在接受一个 ContainerInput 而不是 ClickType
    • ClickType -> ContainerInput

新标签提供者

添加了一个新的 TagsProvider,它提供了一个处理 Holder$Reference 的工具,称为 HolderTagProvider。这仅由 PotionTagsProvider 使用。

此外,TagBuilder 现在提供了一种设置标签上 replace 字段的方法,该方法在反序列化期间删除所有先前读取的条目。

  • net.minecraft.data.tags
    • FeatureTagsProvider - 用于 ConfiguredFeature 的标签提供器。
    • HolderTagProvider - 一个带有通过其引用持有者附加标签的工具的标签提供器。
    • KeyTagProvider#tag 现在有一个重载,指示是否替换标签中的条目。
    • PotionTagsProvider - 用于药水标签的提供器。
    • TradeRebalanceTradeTagsProvider - 用于交易重新平衡的村民交易标签提供器。
    • VillagerTradesTagsProvider - 用于村民交易标签的提供器。
  • net.minecraft.tags
    • FeatureTags - 用于 ConfiguredFeature 的标签。
    • TagBuilder#shouldReplace, setReplace - 处理 replace 字段,该字段在反序列化期间删除所有先前读取的条目。

测试环境状态追踪

TestEnvironmentDefinition 现在可以跟踪创建时世界的原始状态,以便在运行时正确恢复。这是通过一个称为 ‘SavedDataType’ 的泛型完成的。在 setup 上,每个环境将返回表示修改内容原始状态的泛型数据。然后,在 teardown 上,原始状态将恢复到关卡中,以供下一个测试用例使用。

// 泛型应表示存储在关卡上的原始数据
public record RespawnEnvironment(LevelData.RespawnData respawn) implements TestEnvironmentDefinition<LevelData.RespawnData> {

    @Override
    public LevelData.RespawnData setup(ServerLevel level) {
        // 修改关卡同时记录原始状态。
        var original = level.getRespawnData();
        level.setRespawnData(this.respawn);

        // 返回原始状态。
        return original;
    }

    @Override
    public void teardown(ServerLevel level, LevelData.RespawnData original) {
        // 将关卡状态重置为原始值。
        level.setRespawnData(original);
    }
    
    @Override
    public MapCodec<RespawnEnvironment> codec() {
        // 在此处返回注册的 MapCodec。
        // ...
    }
}
  • net.minecraft.gametest.framework.TestEnvironmentDefinition 现在有一个泛型表示测试环境执行的给定修改的原始状态
    • setup 现在返回表示原始状态的泛型
    • teardown 不再是默认的,接受要恢复的原始状态
    • activate, $Activation - 处理一个活动的测试环境。

类型化实例

TypedInstance 是一个附加到某些对象的接口,这些对象表示某个其他“类型”对象的实例。例如,EntityEntityType 的类型化实例,或者 BlockStateBlock 的类型化实例。此接口旨在作为一种标准方法,提供对类型 Holder 的访问,并通过 is 检查后备类型(因此也是实例)是否等同于某个标识符、标签或原始对象。

// 对于某个 Entity entity,检查 EntityType
entity.is(EntityType.PLAYER);

// 对于某个 ItemStack itemStack,检查 Item
itemStack.is(ItemTags.BUTTONS);

// 对于某个 BlockEntity blockEntity,检查 BlockEntityType
blockEntity.is(BlockEntityType.CHEST);

// 对于某个 BlockState blockState,检查 Block
blockState.is(Blocks.DIRT);

// 对于某个 FluidState fluidState,检查 Fluid
fluidState.is(FluidTags.WATER);
  • net.minecraft.core.TypedInstance - 一个表示此对象是某个其他“类型”对象的实例的接口。
  • net.minecraft.world.entity
    • Entity 现在实现 TypedInstance<EntityType<?>>
    • EntityType#is -> TypedInstance#is
      • 现在在 Entity 实例上
  • net.minecraft.world.item.ItemStack 现在实现 TypedInstance<Item>
    • getItemHolder -> typeHolder
    • getTags -> tags
  • net.minecraft.world.level.block.entity
    • BlockEntity 现在实现 TypedInstance<BlockEntityType>
    • BlockEntityType#getKey 已移除
  • net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase 现在实现 TypedInstance<Block>
    • getBlockHolder -> typeHolder
    • getTags -> tags
  • net.minecraft.world.level.material.FluidState 现在实现 TypedInstance<Fluid>
    • holder -> typeHolder
    • getTags -> tags

实体纹理与成年幼年模型

assets/minecraft/textures/entity/* 中的实体纹理现已分类到子目录中(例如,熊猫纹理的 entity/panda,或猪纹理的 entity/pig)。大多数纹理已以实体类型开头后跟下划线及其变体命名(例如,喷溅箭的 arrow_tipped,冷猪变体的 pig_cold,或棕色熊猫变体的 panda_brown)。

此外,一些动物模型已拆分为幼年和成年变体的单独类。这些模型要么直接扩展抽象模型实现(例如 AbstractFelineModel),要么扩展原始模型类(例如 PigModel)。

  • net.minecraft.client.animation.definitions
    • BabyArmadilloAnimation - 幼年犰狳的动画。
    • BabyAxolotlAnimation - 幼年美西螈的动画。
    • BabyRabbitAnimation - 幼年兔子的动画。
    • CamelBabyAnimation - 幼年骆驼的动画。
    • FoxBabyAnimation - 幼年狐狸的动画。
    • RabbitAnimation - 兔子的动画。
  • net.minecraft.client.model
    • HumanoidModel
      • ADULT_ARMOR_PARTS_PER_SLOT, BABY_ARMOR_PARTS_PER_SLOT - 装备槽位到模型部件键的映射。
      • createBabyArmorMeshSet - 为幼年类人生物创建盔甲模型集。
      • createArmorMeshSet 现在可以接受一个装备槽位到要保留的模型部件键的映射
      • setAllVisible 已移除
    • QuadrupedModel 现在有一个接受 RenderType 函数的构造函数
  • net.minecraft.client.model.animal.armadillo
    • AdultArmadilloModel - 成年犰狳的实体模型。
    • ArmadilloModel 现在是抽象的
      • 构造函数现在接受行走、卷起/展开和窥视动画的定义
      • BABY_TRANSFORMER 已直接合并到 BabyArmadilloModel 的层定义中
      • HEAD_CUBE, RIGHT_EAR_CUBE, LEFT_EAR_CUBE 现在是 protected 而不是 private
      • createBodyLayer -> AdultArmadilloModel#createBodyLayer, BabyArmadilloModel#createBodyLayer
    • BabyArmadilloModel - 幼年犰狳的实体模型。
  • net.minecraft.client.model.animal.axolotl.AxolotlModel -> AdultAxolotlModel, BabyAxolotlModel
  • net.minecraft.client.model.animal.bee
    • AdultBeeModel - 成年蜜蜂的实体模型。
    • BabyBeeModel - 幼年蜜蜂的实体模型。
    • BeeModel 现在是抽象的
      • BABY_TRANSFORMER 已直接合并到 BabyBeeModel 的层定义中
      • BONE, STINGER, FRONT_LEGS, MIDDLE_LEGS, BACK_LEGS 现在是 protected 而不是 private
      • bone 现在是 protected 而不是 private
      • createBodyLayer -> AdultBeeModel#createBodyLayer, BabyBeeModel#createBodyLayer
      • bobUpAndDown - 以期望的速度上下摆动蜜蜂,取决于其当前年龄。
  • net.minecraft.client.model.animal.camel
    • AdultCamelModel - 成年骆驼的实体模型。
    • BabyCamelModel - 幼年骆驼的实体模型。
    • CamelModel 现在是抽象的
      • 构造函数现在接受行走、坐下(带/不带姿势)、站立、闲置和冲刺动画的定义
      • BABY_TRANSFORMER 已直接合并到 BabyCamelModel 的层定义中
      • createBodyLayer -> AdultCamelModel#createBodyLayer, BabyCamelModel#createBodyLayer
    • CameSaddleModel 现在扩展 AdultCamelModel 而不是 CamelModel
  • net.minecraft.client.model.animal.chicken
    • AdultChickenModel - 成年鸡的实体模型。
    • BabyChickenModel - 幼年鸡的实体模型。
    • ChickenModel 现在是抽象的
      • RED_THING -> AdultChickenModel#RED_THING
      • BABY_TRANSFORMER 已直接合并到 BabyChickenModel 的层定义中
      • createBodyLayer -> AdultChickenModel#createBodyLayer
      • createBaseChickenModel -> AdultChickenModel#createBaseChickenModel
    • ColdChickenModel 现在扩展 AdultChickenModel
  • net.minecraft.client.model.animal.cow.BabyCowModel - 幼年牛的实体模型。
  • net.minecraft.client.model.animal.dolphin.BabyDolphinModel - 幼年海豚的实体模型。
  • net.minecraft.client.model.animal.equine
    • AbstractEquineModel 现在有一个直接指定要使用的 ModelPart 的重载
      • BABY_TRANSFORMER 已直接合并到 BabyDonkeyModel 的层定义中
      • rightHindLeg, leftHindLeg, rightFrontLeg, leftFrontLeg 现在是 protected 而不是 private
      • createBabyMesh -> BabyHorseModel#createBabyMesh,不是一对一
      • offsetLegPositionWhenStanding - 当实体站立时偏移腿的位置。
      • getLegStandAngle, getLegStandingYOffset, getLegStandingZOffset, getLegStandingXRotOffset, getTailXRotOffset - 马模型各部分的偏移和角度。
      • animateHeadPartsPlacement - 根据其进食和站立状态动画头部。
    • BabyDonkeyModel - 幼年驴的实体模型。
    • BabyHorseModel - 幼年马的实体模型。
    • DonkeyModel 现在有一个直接指定要使用的 ModelPart 的重载
      • createBabyLayer -> BabyDonkeyModel#createBabyLayer
    • EquineSaddleModel#createFullScaleSaddleLayer 已移除 合并到 createSaddleLayer 中,移除了幼年变体
  • net.minecraft.client.model.animal.feline
    • CatModel -> AdultCatModel, BabyCatModel; 不是一对一
    • FelineModel -> AbstractFelineModel,不是一对一
      • 实现为 AdultFelineModelBabyFelineModel
    • OcelotModel -> AdultOcelotModel, BabyOcelotModel; 不是一对一
  • net.minecraft.client.model.animal.fox
    • AdultFoxModel - 成年狐狸的实体模型。
    • BabyFoxModel - 幼年狐狸的实体模型。
    • FoxModel 现在是抽象的
      • BABY_TRANSFORMER 已直接合并到 BabyFoxModel 的层定义中
      • body, rightHindLeg, leftHindLeg, rightFontLeg, leftFrontLeg, tail 现在是 protected 而不是 private
      • createBodyLayer -> AdultFoxModel#createBodyLayer, BabyFoxModel#createBodyLayer
      • set*Pose - 设置狐狸当前姿势的方法。
  • net.minecraft.client.model.animal.goat
    • BabyGoatModel - 幼年山羊的实体模型。
    • GoatModel#BABY_TRANSFORMER 已直接合并到 BabyGoatModel 的层定义中
  • net.minecraft.client.model.animal.llama
    • BabyLlamaModel - 幼年羊驼的实体模型。
    • LlamaModel#createBodyLayer 不再接受表示实体是否为幼年的 boolean
  • net.minecraft.client.model.animal.panda
    • BabyPandaModel - 幼年熊猫的实体模型。
    • PandaModel
      • BABY_TRANSFORMER 已直接合并到 BabyPandaModel 的层定义中
      • animateSitting - 动画熊猫坐下。
  • net.minecraft.client.model.animal.pig.BabyPigModel - 幼年猪的实体模型。
  • net.minecraft.client.model.animal.polarbear
    • BabyPolarBearModel - 幼年北极熊的实体模型。
    • PolarBearModel#BABY_TRANSFORMER 已直接合并到 BabyPolarBearModel 的层定义中
  • net.minecraft.client.model.animal.rabbit
    • AdultRabbitModel - 成年兔子的实体模型。
    • BabyRabbitModel - 幼年兔子的实体模型。
    • RabbitModel 现在是抽象的
      • 构造函数现在接受跳跃和空闲头部倾斜的两个动画定义
      • FRONT_LEGS, BACK_LEGS - 实体腿的子名称。
      • LEFT_HAUNCH, RIGHT_HAUNCH 现在是 protected
      • createBodyLayer -> AdultRabbitModel#createBodyLayer, BabyRabbitModel#createBodyLayer; 不是一对一
  • net.minecraft.client.model.animal.sheep
    • BabySheepModel - 幼年羊的实体模型。
    • SheepModel#BABY_TRANSFORMER 已直接合并到 BabySheepModel 的层定义中
  • net.minecraft.client.model.animal.sniffer
    • SnifferModel#BABY_TRANSFORMER 已直接合并到 SniffletModel 的层定义中
    • SniffletModel - 幼年嗅探兽的实体模型。
  • net.minecraft.client.model.animal.squid
    • BabySquidModel - 幼年鱿鱼的实体模型。
    • SquidModel#createTentacleName 现在是 protected 而不是 private
  • net.minecraft.client.model.animal.turtle
    • AdultTurtleModel - 成年海龟的实体模型。
    • BabyTurtleModel - 幼年海龟的实体模型。
    • TurtleModel 现在是抽象的
      • 构造函数现在可以接受渲染类型函数
      • BABY_TRANSFORMER 已直接合并到 BabyTurtleModel 的层定义中
      • createBodyLayer -> AdultTurtleModel#createBodyLayer, BabyTurtleModel#createBodyLayer
  • net.minecraft.client.model.animal.wolf
    • AdultWolfModel - 成年狼的实体模型。
    • BabyWolfModel - 幼年狼的实体模型。
    • WolfModel 现在是抽象的
      • ModelPart 字段现在都是 protected
      • createMeshDefinition -> AdultWolfModel#createBodyLayer, BabyWolfModel#createBodyLayer; 不是一对一
      • shakeOffWater - 甩水时设置身体旋转。
      • setSittingPose - 设置狼的坐姿。
  • net.minecraft.client.model.geom
    • ModelLayers
      • COLD_CHICKEN_BABY 已移除
      • COLD_PIG_BABY 已移除
      • PIG_BABY_SADDLE 已移除
      • SHEEP_BABY_WOOL_UNDERCOAT 已移除
      • WOLF_BABY_ARMOR 已移除
      • DONKEY_BABY_SADDLE 已移除
      • HORSE_BABY_ARMOR 已移除
      • HORSE_BABY_SADDLE 已移除
      • MULE_BABY_SADDLE 已移除
      • SKELETON_HORSE_BABY_SADDLE 已移除
      • UNDEAD_HORSE_BABY_ARMOR 已移除
      • ZOMBIE_HORSE_BABY_SADDLE 已移除
      • STRIDER_BABY_SADDLE 已移除
    • PartNames#WAIST - 腰部部件。
  • net.minecraft.client.model.monster.hoglin
    • BabyHoglinModel - 幼年疣猪兽的实体模型。
    • HoglinModel
      • BABY_TRANSFORMER 已直接合并到 BabyHoglinModel 的层定义中
      • head 现在是 protected 而不是 private
      • createBabyLayer -> BabyHoglinModel#createBodyLayer
  • net.minecraft.client.model.monster.piglin
    • AbstractPiglinModel 现在是抽象的
      • leftSleeve, rightSleeve, leftPants, rightPants, jacket 已移除
      • ADULT_EAR_ANGLE_IN_DEGREES, BABY_EAR_ANGLE_IN_DEGREES - 猪灵耳朵的角度。
      • createMeshAdultPiglinModel#createBodyLayer, AdultZombifiedPiglinModel#createBodyLayer, BabyPiglinModel#createBodyLayer, BabyZombifiedPiglinModel#createBodyLayer 取代
      • createBabyArmorMeshSet - 为幼年猪灵模型创建盔甲网格。
      • getDefaultEarAngleInDegrees - 获取默认耳朵角度。
    • AdultPiglinModel - 成年猪灵的实体模型。
    • AdultZombifiedPiglinModel - 成年僵尸猪灵的实体模型。
    • BabyPiglinModel - 幼年猪灵的实体模型。
    • BabyZombifiedPiglinModel - 幼年僵尸猪灵的实体模型。
    • PiglinModel 现在是抽象的
    • ZombifiedPiglinModel 现在是抽象的
  • net.minecraft.client.model.monster.strider
    • AdultStriderModel - 成年炽足兽的实体模型。
    • BabyStriderModel - 幼年炽足兽的实体模型。
    • StriderModel 现在是抽象的
      • BABY_TRANSFORMER 已直接合并到 BabyStriderModel 的层定义中
      • rightLeg, leftLeg, body 现在是 protected 而不是 private
      • SPEED - 移动动画的速度标量。
      • customAnimations - 额外的动画设置。
      • animateBristle - 动画炽足兽的鬃毛。
  • net.minecraft.client.model.monster.zombie
    • BabyDrownedModel - 幼年溺尸的实体模型。
    • BabyZombieModel - 幼年僵尸的实体模型。
    • BabyZombieVillagerModel - 幼年僵尸村民的实体模型。
  • net.minecraft.client.model.npc
    • BabyVillagerModel - 幼年村民的实体模型。
    • VillagerModel#BABY_TRANSFORMER 已直接合并到 BabyVillagerModel 的层定义中
  • net.minecraft.client.renderer.entity
    • AxolotlRenderer 现在接受一个 EntityModel<AxolotlRenderState> 作为其泛型
    • CamelHuskRenderer 现在扩展 MobRenderer 而不是 CamelRenderer
    • CamelRenderer#createCamelSaddleLayer 现在是 static
    • CatRenderer 现在接受一个 AbstractFelineModel 作为其泛型
    • DonkeyRenderer 现在接受一个 EquipmentClientInfo$LayerTypeModelLayerLocation 用于鞍层和模型,并将 DonkeyRenderer$Type 拆分为成年类型和幼年类型
      • $Type
        • DONKEY_BABY - 驴的幼年变体。
        • MULE_BABY - 骡的幼年变体。
    • OcelotRenderer 现在接受一个 AbstractFelineModel 作为其泛型
    • UndeadHorseRenderer 现在接受一个 EquipmentClientInfo$LayerTypeModelLayerLocation 用于鞍层和模型,并将 UndeadHorseRenderer$Type 拆分为成年类型和幼年类型
      • $Type
        • SKELETON_BABY - 骷髅马的幼年变体。
        • ZOMBIE_BABY - 僵尸马的幼年变体。
  • net.minecraft.client.renderer.entity.layers.CatCollarLayer 现在接受一个 AbstractFelineModel 作为其泛型
  • net.minecraft.client.renderer.entity.state
    • AxolotlRenderState
      • swimAnimation - 游泳的状态。
      • walkAnimationState - 在地面(非水下)行走的状态。
      • walkUnderWaterAnimationState - 在水下行走的状态。
      • idleUnderWaterAnimationState - 在水下但未在地面闲置的状态。
      • idleUnderWaterOnGroundAnimationState - 在水下接触海底时闲置的状态。
      • idleOnGroundAnimationState - 在地面(非水下)闲置的状态。
      • playDeadAnimationState - 装死的状态。
    • RabbitRenderState
      • hopAnimationState - 实体正在执行的跳跃状态。
      • idleHeadTiltAnimationState - 执行空闲动画时头部倾斜的状态。
  • net.minecraft.client.resources.model.EquipmentClientInfo$LayerType#HUMANOID_BABY - 幼年类人生物装备层。
  • net.minecraft.sounds.SoundEvents#PIG_EAT_BABY - 幼年猪进食时播放的声音。
  • net.minecraft.world.entity.AgeableMob
    • canUseGoldenDandelion - 是否可以使用金蒲公英来锁定实体的年龄。
    • setAgeLocked - 将实体设置为年龄锁定。
    • makeAgeLockedParticle - 在锁定实体年龄时创建粒子。
    • AGE_LOCK_DOWNWARDS_MOVING_PARTICLE_Y_OFFSET - 粒子起始位置的 Y 偏移量。
  • net.minecraft.world.entity.animal.axolotl.Axolotl
    • swimAnimation - 游泳的状态。
    • walkAnimationState - 在地面(非水下)行走的状态。
    • walkUnderWaterAnimationState - 在水下行走的状态。
    • idleUnderWaterAnimationState - 在水下但未在地面闲置的状态。
    • idleUnderWaterOnGroundAnimationState - 在水下接触海底时闲置的状态。
    • idleOnGroundAnimationState - 在地面(非水下)闲置的状态。
    • playDeadAnimationState - 装死的状态。
    • $AnimationState -> $AxolotlAnimationState
  • net.minecraft.world.entity.animal.chicken.ChickenVariant 现在接受一个幼年纹理的资源
  • net.minecraft.world.entity.animal.cow.CowVariant 现在接受一个幼年纹理的资源
  • net.minecraft.world.entity.animal.cat.CatVariant 现在接受一个幼年纹理的资源
    • CatVariant#assetInfo - 根据实体是否为幼年获取实体纹理。
  • net.minecraft.world.entity.animal.equine.AbstractHorse#BABY_SCALE - 幼年大小与成年相比的比例。
  • net.minecraft.world.entity.animal.frog.Tadpole
    • ageLockParticleTimer - 年龄锁定实体的粒子应生成的计时器。
    • setAgeLocked, isAgeLocked - 处理蝌蚪的年龄锁定。
  • net.minecraft.world.entity.animal.goat.Goat
    • BABY_DEFAULT_X_HEAD_ROT - 幼年变体的默认头部 X 旋转。
    • MAX_ADDED_RAMMING_X_HEAD_ROT - 最大头部 X 旋转。
    • addHorns, removeHorns 已移除
  • net.minecraft.world.entity.animal.pig.PigVariant 现在接受一个幼年纹理的资源
  • net.minecraft.world.entity.animal.rabbit.Rabbit
    • hopAnimationState - 实体正在执行的跳跃状态。
    • idleHeadTiltAnimationState - 执行空闲动画时头部倾斜的状态。
  • net.minecraft.world.entity.animal.wolf
    • WolfSoundVariant -> WolfSoundVariant$WolfSoundSet
      • 该类本身现在持有成年狼和幼年狼的两个声音集。
    • WolfSoundVariants$SoundSet#getSoundEventSuffix -> getSoundEventIdentifier
  • net.minecraft.world.entity.animal.wolf.WolfVariant 现在接受一个幼年变体的资源信息
  • net.minecraft.world.item.equipment.EquipmentAssets#TRADER_LLAMA_BABY - 幼年流浪商羊驼的装备资源。

interactAt 的移除

Entity#interactAt 已被移除,所有进一步的调用都已合并到 Entity#interact 中。最初,如果命中结果在实体的交互范围内,则调用 Entity#interactAt。如果 interactAt 没有消耗该操作(即 InteractionResult#consumesAction 返回 false),则调用 Entity#interact。现在,如果在实体的交互范围内,则调用 Entity#interact,并接受交互位置的 Vec3

// 在某个 Entity 子类中

@Override
public InteractionResult interact(Player player, InteractionHand hand, Vec3 location) {
    // 处理交互
    super.interact(player, hand, location);
}

interactAt 检查结果是否未消耗交互,如果没有则调用 interact 现在,使用实体命中调用 interact

  • net.minecraft.client.multiplayer.MultiPlayerGameMode
    • interact 现在接受 EntityHitResult
    • interactAt 已移除
  • net.minecraft.world.entity.Entity
    • interact 现在接受一个 Vec3 表示交互的位置
    • interactAt 已移除
  • net.minecraft.world.entity.player.Player#interactOn 现在接受一个 Vec3 表示交互的位置

ChunkPos,现在是一个记录

ChunkPos 现在是一个记录。BlockPos 构造函数已被 ChunkPos#containing 取代,而打包的 long 构造函数已被 ChunkPose#unpack 取代。

  • net.minecraft.world.level.ChunkPos 现在是一个记录
    • ChunkPos(BlockPos) -> containing
    • ChunkPos(long) -> unpack
    • toLong, asLong -> pack

不再有绊线管线

绊线渲染管线已被完全移除。现在,绊线使用带有 alpha_cutoff_bias 为 0.1 的 cutout 用于纹理。

  • net.minecraft.client.renderer.RenderPipelines#TRIPWIRE_BLOCK, TRIPWIRE_TERRAIN 已移除
  • net.minecraft.client.renderer.chunk
    • ChunkSectionLayer#TRIPWIRE 已移除
    • ChunkSectionLayerGroup#TRIPWIRE 已移除
  • net.minecraft.client.renderer.rendertype.RenderTypes#tripwireMovingBlock 已移除

活动与大脑

活动(Activity)定义了生物在特定阶段的行为方式,现在通过 ActivityData 存储和传递。这包含活动类型、要执行的行为及其优先级、活动激活的条件,以及活动停止时要擦除的记忆。Brain#provider 现在接受一个 $ActivitySupplier 来构造实体执行的一系列 ActivityData

大脑也略有变化。首先,Brain 本身不能直接序列化。相反,大脑被 $Packed 到记录中,持有其当前记忆的映射。要获取使用的记忆类型,通常从 Sensor#requires 中提取。此外,LivingEntity#brainProvider 不再存在,而是选择将提供器存储在实体本身的静态常量中。这意味着大脑现在完全通过 makeBrain 方法构建,接受之前的 $Packed 数据:

// 对于某个扩展 LivingEntity 的 ExampleEntity
// 假设扩展了 Mob 子类
private static final Brain.Provider<ExampleEntity> BRAIN_PROVIDER = Brain.provider(
    // 实体使用的传感器列表。
    ImmutableList.of(),
    // 一个接受实体并返回活动列表的函数。
    entity -> List.of(
        new ActivityData(
            // 活动类型
            Activity.CORE,
            // 优先级和行为对的列表
            ImmutableList.of(Pair.of(0, new MoveToTargetSink())),
            // 活动运行所需的记忆条件集
            // 例如,此记忆值必须存在
            ImmutableSet.of(Pair.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_PRESENT)),
            // 活动停止时要擦除的记忆集
            ImmutableSet.of(MemoryModuleType.ATTACK_TARGET)
        )
    )
);

@Override
protected Brain.Provider<ExampleEntity> makeBrain(Brain.Packed packedBrain) {
    // 构建大脑,填充任何先前的记忆
    return BRAIN_PROVIDER.makeBrain(this, packedBrain);
}
  • net.minecraft.world.entity.LivingEntity
    • brainProvider 已移除
    • makeBrain 现在接受一个 Brain$Packed 而不是 Dynamic
  • net.minecraft.world.entity.ai
    • ActivityData - 一个记录,包含正在执行的活动、该活动中要执行的行为、任何记忆条件以及停止后要擦除的记忆。
    • Brain 现在是 protected 的,接受一个 ActivityData 列表、一个 MemoryMap 而不是不可变的记忆列表、一个 RandomSource,并且不提供 Codec
      • 公共构造函数不再接受任何参数
      • provider 现在有一个只接受传感器类型的重载,默认记忆类型为空列表
        • 一些 provider 方法也接受要执行的 Brain$ActivitySupplier
      • codec, serializeStartpack, Brain$Packed 取代
      • addActivityAndRemoveMemoryWhenStopped, addActivityWithConditions 合并到 addActivity
        • 或者使用 ActivityData#create
      • copyWithoutBehaviors 已移除
      • getMemoriesforEach 取代
      • $ActivitySupplier - 为实体创建活动列表。
      • $MemoryValue 已移除
      • $Packed - 一个包含序列化大脑到磁盘的数据的记录。
      • $Provider#makeBrain 现在接受实体和要反序列化记忆的 Brain$Packed
      • $Visitor - 访问大脑内的记忆,无论是已定义但为空、存在还是带有计时器存在。
  • net.minecraft.world.entity.ai.behavior.VillagerGoalPackages#get*Package 不再接受 VillagerProfession
  • net.minecraft.world.entity.ai.memory
    • ExpirableValue -> MemorySlot,不是一对一
      • 原始的 ExpirableValue 现在是一个记录,定义记忆何时过期,而不是自己更新
    • MemoryMap - 将记忆类型链接到其存储值的映射。
    • MemoryModuleType - 记忆是否可以序列化。
  • net.minecraf.tworld.entity.ai.sensing.Sensor#randomlyDelayStart - 延迟传感器多长时间。
  • net.minecraft.world.entity.animal.allay.AllayAi
    • SENSOR_TYPES, MEMORY_TYPES -> BRAIN_PROVIDER,现在是 private;不是一对一
    • makeBrain -> getActivities,不是一对一
  • net.minecraft.world.entity.animal.armadillo.ArmadilloAi#makeBrain, brainProvider -> getActivities,现在是 protected,不是一对一
  • net.minecraft.world.entity.animal.axolotl
    • AxolotlSENSOR_TYPES -> BRAIN_PROVIDER,现在是 private;不是一对一
    • AxolotlAi
      • makeBrain -> getActivities,不是一对一
      • initPlayDeadActivity,现在是 protected,不再接受任何参数
      • initFightActivity,现在是 protected,不再接受任何参数
      • initCoreActivity,现在是 protected,不再接受任何参数
      • initIdleActivity,现在是 protected,不再接受任何参数
  • net.minecraft.world.entity.animal.camel.CamelAi#makeBrain, brainProvider -> getActivities,现在是 protected,不是一对一
  • net.minecraft.world.entity.animal.frog
    • Frog#SENSOR_TYPES -> BRAIN_PROVIDER,现在是 private;不是一对一
    • FrogAi#makeBrain -> getActivities,不是一对一
    • Tadpole#SENSOR_TYPES -> BRAIN_PROVIDER,现在是 private;不是一对一
  • net.minecraft.world.entity.animal.frog.TadpoleAi#makeBrain -> getActivities,现在是 public,不是一对一
  • net.minecraft.world.entity.animal.goat
    • Goat#SENSOR_TYPES -> BRAIN_PROVIDER,现在是 private;不是一对一
    • GoatAi#makeBrain -> getActivities,不是一对一
  • net.minecraft.world.entity.animal.golem.CopperGolemAi#makeBrain, brainProvider -> getActivities,现在是 protected,不是一对一
  • net.minecraft.world.entity.animal.happyghast.HappyGhastAi#makeBrain, brainProvider -> getActivities,现在是 protected,不是一对一
  • net.minecraft.world.entity.animal.nautilus
    • NautilusAi
      • SENSOR_TYPES,MEMORY_TYPES -> Nautilus#BRAIN_PROVIDER,现在是 private,不是一对一
      • makeBrain, brainProvider -> getActivities,现在是 public,不是一对一
    • ZombieNautilusAi
      • SENSOR_TYPES,MEMORY_TYPES -> ZombieNautilus#BRAIN_PROVIDER,现在是 private,不是一对一
      • makeBrain, brainProvider -> getActivities,现在是 public,不是一对一
  • net.minecraft.world.entity.animal.sniffer.SnifferAi#makeBrain -> getActivities,现在是 public,不是一对一
  • net.minecraft.world.entity.monster.Zoglin
    • SENSOR_TYPES -> BRAIN_PROVIDER,现在是 private,不是一对一
    • getActivities - 僵尸疣猪兽执行的活动。
  • net.minecraft.world.entity.monster.breeze.BreezeAi#makeBrain -> getActivities,不是一对一
  • net.minecraft.world.entity.monster.creaking.CreakingAi#makeBrain, brainProvider -> getActivities,现在是 protected,不是一对一
  • net.minecraft.world.entity.monster.hoglin
    • Hoglin#SENSOR_TYPES -> BRAIN_PROVIDER,现在是 private;不是一对一
    • HoglinAi#makeBrain -> getActivities,不是一对一
  • net.minecraft.world.entity.monster.piglin
    • Piglin#SENSOR_TYPES,MEMORY_TYPES -> BRAIN_PROVIDER,现在是 private,不是一对一
    • PiglinAi#makeBrain -> getActivities,现在是 public,不是一对一
    • PiglinBrute#SENSOR_TYPES,MEMORY_TYPES -> BRAIN_PROVIDER,现在是 private,不是一对一
    • PiglinBruteAi#makeBrain -> getActivities,现在是 public,不是一对一
  • net.minecraft.world.entity.monster.warden.WardenAi#makeBrain -> getActivities,不是一对一

文件修复器

文件修复器是一个新系统,用于帮助在版本之间升级游戏文件,与数据修复器协同工作。类似于文件中的数据可以通过数据修复器在 Minecraft 版本之间修改或“升级”,文件修复器可以修改世界目录中的任何内容,从移动文件和目录到直接删除它们。因此,文件修复器总是在数据修复器之前应用。

与数据修复器升级时不同,文件修复器会改变世界文件夹的结构。因此,降级几乎不可能,因为文件名和位置很可能已更改位置。

文件修复器通过 FileFix 应用,它使用 makeFixer 定义要对文件执行的一些操作。通常通过 addFileContentFix 完成,通过 FileAccess 提供对所需文件的访问,然后像任何其他 Dynamic 实例一样修改数据。操作通常定义为 FileFixOperation,可以移动文件结构。

然后通过 FileFixerUpper 应用文件修复,它使用写时复制文件系统对文件进行操作。修复器使用 $Builder 构建,使用 addSchemaaddFixer 为所需版本应用修复器。在升级过程中,文件在临时文件夹中创建,然后移动到世界文件夹。原始世界文件夹在删除之前被移动到另一个文件夹。

  • net.minecraft.client.gui.screens.FileFixerAbortedScreen - 当文件修复被中止时显示的屏幕。
  • net.minecraft.client.gui.screens.worldselection.FileFixerProgressScreen - 尝试显示升级和修复世界文件的进度时显示的屏幕。
  • net.minecraft.server.packs.linkfs
    • DummyFileAttributes -> .minecraft.util.DummyFileAttributes
    • LinkFSPath
      • DIRECTORY_ATTRIBUTES -> DummyFileAttributes#DIRECTORY
      • FILE_ATTRIBUTES -> DummyFileAttributes#FILE
  • net.minecraft.util
    • ExtraCodecs
      • pathCodec - 路径的编解码器,从字符串转换并使用 Unix 分隔符存储。
      • relaiveNormalizedSubPathCodec - 路径的编解码器,已标准化并验证以确保其是相对的。
      • guardedPathCodec - 路径的编解码器,从某个基础路径解析和相对化。
    • FileUtil
      • isPathNormalized, createPathToResource 已移除
      • isEmptyPath - 返回路径是否为空。
    • Util#safeMoveFile - 使用给定选项安全地将文件从某个源移动到目标。
  • net.minecraft.util.filefix
    • AbortedFileFixException - 当文件修复已中止且无法还原移动时抛出的异常。
    • AtmoicMoveNotSupportedFileFixException - 当用户文件系统不支持原子移动时抛出的异常。
    • CanceledFileFixException - 当文件修复升级过程被取消时抛出的异常。
    • FailedCleanupFileFixException - 当文件修复无法移动或删除文件夹进行清理时抛出的异常。
    • FileFix - 对文件执行某些操作的修复器。
    • FileFixerUpper - 要执行操作的文件修复器。
    • FileFixException - 尝试通过文件修复器升级世界时抛出的异常。
    • FileFixUtil - 执行某些文件操作的工具。
    • FileSystemCapabilities - 目录中文件系统的能力。
  • net.minecraft.util.filefix.access
    • ChunkNbt - 处理升级区块 nbt。
    • CompressedNbt - 处理升级压缩的 nbt 文件。
    • FileAccess - 提供对某些文件资源的引用,给定其关系。
    • FileAccessProvider - 文件访问的提供器,给定与源的关系。
    • FileRelation - 文件与某个源路径的关系的定义。
    • FileResourceType - 定义要访问的资源类型。
    • FileResourceTypes - 所有定义的文件资源类型。
    • LevelDat - 处理升级 level dat。
    • PlayerData - 处理升级玩家数据。
    • SavedDataNbt - 处理升级保存的数据。
  • net.minecraft.util.filefix.fixes.* - 要应用到文件的原版修复。
  • net.minecraft.util.filefix.operations
    • ApplyInFolders - 在相关文件夹内应用给定操作。
    • DeleteFileOrEmptyDirectory - 删除目标文件或空目录。
    • FileFixOperation - 在某个基础目录内执行的操作。
    • FileFixOperations - 所有原版文件修复操作。
    • GroupMove - 移动某个目录,对其内容应用任何移动操作。
    • ModifyContent - 修改文件的内容。
    • Move - 将文件从某个源移动到某个目标。
    • RegexMove - 移动所有匹配给定源模式的文件到目标,替换匹配的部分。
  • net.minecraft.util.filefix.virtualfilesystem
    • CopyOnWriteFileStore - 使用写时复制原理的文件存储。
    • CopyOnWriteFileSystem - 使用写时复制原理的文件系统。
    • CopyOnWriteFSPath - 使用写时复制原理的路径。
    • CopyOnWriteFSProvider - 使用写时复制原理的文件系统提供器。
    • DirectoryNode - 某个写时复制文件系统路径的目录节点。
    • FileMove - 一个记录,包含文件被移动到的路径。
    • FileNode - 某个写时复制文件系统路径的文件节点。
    • Node - 某个写时复制文件系统路径的节点。
  • net.minecraft.util.filefix.virtualfilesystem.exception
    • CowFSCreationException - 当无法创建文件系统时的 CowFSFileSystemException
    • CowFSDirectoryNotEmptyException - 专门针对写时复制系统的 DirectoryNotEmptyException
    • CowFSFileAlreadyExistsException - 专门针对写时复制系统的 FileAlreadyExistsException
    • CowFSFileSystemException - 专门针对写时复制系统的 FileSystemException
    • CowFSIllegalArgumentException - 尝试在写时复制系统上操作时的 IllegalArgumentException
    • CowFSNoSuchFileException - 专门针对写时复制系统的 NoSuchFileException
    • CowFSNotDirectoryException - 专门针对写时复制系统的 NotDirectoryException
    • CowFSSymlinkException - 尝试将写时复制系统与符号链接一起使用时的 CowFSCreationException
  • net.minecraft.util.worldupdate
    • UpgradeProgress
      • getTotalFiles -> getTotalFileFixState,不是一对一
      • addTotalFiles -> addTotalFileFixOperations,不是一对一
      • getTypeFileFixStats, getRunningFileFixerStats - 获取特定文件组的修复器统计信息。
      • incrementFinishedOperations, incrementFinishedOperationsBy - 增加已完成操作的数量。
      • setType, getType - 获取升级进度的类型。
      • setApplicableFixerAmount - 设置运行中文件修复器的已完成操作总数。
      • incrementRunningFileFixer - 增加已完成操作的数量。
      • logProgress - 每秒记录一次升级进度。
      • $FileFixStats - 已执行/已完成操作的计数器。
      • $Type - 对世界数据执行的升级类型。
    • WorldUpgrader 不再接受 WorldData
      • STATUS_* 消息已合并到 UpgradeStatusTranslator
        • 这也包含特定的 datafix 类型
      • running, finished, progress, totalChunks, totalFiles, converted, skipped, progressMap, status 都已移至 UpgradeProgress,存储在 upgradeProgress
      • getProgress -> getTotalProgress,不是一对一
      • $AbstractUpgrader, $SimpleRegionStorageUpgrader -> RegionStorageUpgrader,不再接受提供的 LegacyTagFixer,不是一对一
        • $ChunkUpgrader, $EntityUpgrader, $PoiUpgrader 现在只是在 WorldUpgrader#work 中构造
        • $Builder#setLegacyFixer 已移除
      • $ChunkUpgrader#tryProcessOnePosition 已部分抽象为 getDataFixContentTag, verifyChunkPosAndEraseCache, verifyChunkPos
      • $FileToUpgrade -> FileToUpgrade
  • net.minecraft.world.level.ChunkPos#getRegionX, getRegionZ - 获取区块所在的区域。
  • net.minecraft.world.level.chunk.ChunkGenerator#getTypeNameForDataFixer 现在返回一个可选的 Identifier 而不是 ResourceKey
  • net.minecraft.world.level.chunk.storage
    • LegacyTagFixer 接口已移除
    • RecreatingSimpleRegionStorage 不再接受提供的 LegacyTagFixer
    • SimpleRegionStorage 不再接受提供的 LegacyTagFixer
      • markChunkDone 已移除
  • net.minecraft.world.level.levelgen.structure
    • LegacyStructureDataHandler 类已移除
    • StructureFeatureIndexSavedData 类已移除
  • net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager
    • STRUCTURE_RESOURCE_DIRECTORY_NAME -> STRUCTURE_DIRECTORY_NAME,不是一对一
    • WORLD_STRUCTURE_LISTER, RESOURCE_TEXT_STRUCTURE_LISTER - 结构 nbt 的 ID 转换器。
    • save 现在有一个接受路径、StructureTemplateboolean(是否将数据写为文本)的重载
    • createAndValidatePathToGeneratedStructure -> TemplatePathFactory#createAndValidatePathToStructure,不是一对一
    • worldTemplates, testTemplates - 模板路径工厂。
  • net.minecraft.world.level.levelgen.structure.templatesystem.loader
    • DirectoryTemplateSource - 某个目录的模板源。
    • ResourceManagerTemplateSource - 资源管理器的模板源。
    • TemplatePathFactory - 获取某个结构路径的工厂。
    • TemplateSource - 结构模板的加载器。
  • net.minecraft.world.level.storage
    • LevelStorageSource
      • getLevelDataAndDimensions 现在接受 $LevelStorageAccess
      • readExistingSavedData - 读取任何现有的保存数据。
      • writeGameRules - 将游戏规则写入保存数据。
      • $LevelStorageAccess#releaseTemporarilyAndRun - 释放访问并在重新创建锁之前运行。
        • collectIssues - 收集尝试升级数据时的任何问题。
        • getSummary -> fixAndGetSummary, fixAndGetSummaryFromTag;不是一对一
        • getDataTag -> getUnfixedDataTag,不是一对一
        • getDataTagFallback -> getUnfixedDataTagWithFallback,不是一对一
        • saveDataTag 不再接受 RegistryAccess
        • saveLevelData - 保存 level dat。
    • LevelSummary 现在接受是否需要文件修复
      • UPGRADE_AND_PLAY_WORLD - 告诉用户升级他们的世界并游玩的组件。
      • requiresFileFixing - 关卡是否需要文件修复。
      • $BackupStatus#FILE_FIXING_REQUIRED - 是否需要文件修复才能在此版本上玩此关卡。

聊天权限

聊天系统现在有一组相关的权限,指示玩家可以发送或接收哪些消息。Permissions#CHAT_SEND_MESSAGESCHAT_SEND_COMMANDS 分别确定玩家是否可以发送消息或命令。同样,CHAT_RECEIVE_PLAYER_MESSAGESCHAT_RECEIVE_SYSTEM_MESSAGES 确定玩家是否可以接收来自其他玩家或系统的消息。请注意,所有这些权限仅在客户端处理,不在服务器端验证。

  • net.minecraft.SharedConstants#DEBUG_CHAT_DISABLED - 禁用聊天框的标志。
  • net.minecraft.client
    • GuiMessage -> .multiplayer.chat.GuiMessage
    • GuiMessageTag -> .multiplayer.chat.GuiMessageTag
    • Minecraft
      • getChatStatus -> computeChatAbilities,不是一对一
      • $ChatStatus -> ChatRestriction,不是一对一
  • net.minecraft.client.gui.Gui#setChatDisabledByPlayerShown, isShowingChatDisabledByPlayer - 处理聊天是否被显示的玩家禁用。
  • net.minecraft.client.gui.components
    • ChatComponent
      • GO_TO_RESTRICTIONS_SCREEN - 重定向到限制屏幕的标识符。
      • setVisibleMessageFilter - 设置消息过滤函数。
      • render, captureClickableText 现在接受 $DisplayMode 而不是表示玩家是否在聊天的 boolean
      • addMessage 现在是 private
        • 拆分为 addClientSystemMessage, addServerSystemMessage, addPlayerMessage
      • $DisplayMode - 聊天应如何显示。
    • CommandSuggestions
      • USAGE_FORMAT, USAGE_OFFSET_FROM_BOTTOM, LINE_HEIGHT - 显示命令建议的常量。
      • setRestrictions - 设置可以键入的消息的限制。
      • hasAllowedInput - 聊天框是否允许输入。
  • net.minecraft.client.gui.screens.ChatScreen#USAGE_BACKGROUND_COLOR - 命令建议框的背景颜色。
  • net.minecraft.client.gui.screens.multiplayer.RestrictionsScreen - 用于设置玩家聊天框限制的屏幕。
  • net.minecraft.client.gui.screens.reporting.ReportPlayerScreen 现在接受一个 boolean 表示聊天是否被禁用或阻止
  • net.minecraft.client.multiplayer.chat
    • ChatAbilities - 玩家在聊天框上聊天的限制集。
    • ChatListener
      • handleSystemMessageboolean 现在用于表示系统是否为远程而不是覆盖
        • 覆盖现在通过 handleOverlay 处理
    • GuiMessageSource - 消息的来源。
  • net.minecraft.client.player.LocalPlayer 现在接受 ChatAbilities
    • chatAbilities, refreshChatAbilities - 处理聊天能力。
  • net.minecraft.server.permissions.Permissions
    • CHAT_SEND_MESSAGES - 玩家是否可以发送聊天消息。
    • CHAT_SEND_COMMANDS - 玩家是否可以发送命令。
    • CHAT_RECEIVE_PLAYER_MESSAGES - 玩家是否可以接收其他玩家的消息。
    • CHAT_RECEIVE_SYSTEM_MESSAGES - 玩家是否可以接收系统消息。
    • CHAT_PERMISSIONS - 一组可用的聊天权限。
  • net.minecraft.world.entity.player.Player#displayClientMessage 拆分为当覆盖消息为 false 时的 sendSystemMessage,以及当覆盖消息为 true 时的 sendOverlayMessage

更多实体声音变种注册表

猫、鸡、牛和猪现在有了声音变体:一个数据包注册表对象,指定实体播放的声音。这不需要直接与实际的实体变体相关联,因为它只定义实体播放的声音,通常在 Mob#finalizeSpawn 期间。

对于牛:

// 文件位于:
// - `data/examplemod/cow_sound_variant/example_cow_sound.json`
{
    // 空闲时随机播放的声音事件的注册表名称。
    "ambient_sound": "minecraft:entity.cow.ambient",
    // 被杀死时播放的声音事件的注册表名称。
    "death_sound": "minecraft:entity.cow.death",
    // 受伤时播放的声音事件的注册表名称。
    "hurt_sound": "minecraft:entity.cow.hurt",
    // 踩踏时播放的声音事件的注册表名称。
    "step_sound": "minecraft:entity.cow.step"
}

对于鸡和猪:

// 文件位于:
// - `data/examplemod/chicken_sound_variant/example_chicken_sound.json`
{
    // 实体年龄大于或等于 0(成年)时播放的声音。
    "adult_sounds": {
        // 空闲时随机播放的声音事件的注册表名称。
        "ambient_sound": "minecraft:entity.chicken.ambient",
        // 被杀死时播放的声音事件的注册表名称。
        "death_sound": "minecraft:entity.chicken.death",
        // 受伤时播放的声音事件的注册表名称。
        "hurt_sound": "minecraft:entity.chicken.hurt",
        // 踩踏时播放的声音事件的注册表名称。
        "step_sound": "minecraft:entity.chicken.step"
    },
    // 实体年龄小于 0(幼年)时播放的声音。
    "baby_sounds": {
        "ambient_sound": "minecraft:entity.baby_chicken.ambient",
        "death_sound": "minecraft:entity.baby_chicken.death",
        "hurt_sound": "minecraft:entity.baby_chicken.hurt",
        "step_sound": "minecraft:entity.baby_chicken.step"
    }
}

对于猪:

// 文件位于:
// - `data/examplemod/pig_sound_variant/example_pig_sound.json`
{
    // 实体年龄大于或等于 0(成年)时播放的声音。
    "adult_sounds": {
        // 空闲时随机播放的声音事件的注册表名称。
        "ambient_sound": "minecraft:entity.pig.ambient",
        // 被杀死时播放的声音事件的注册表名称。
        "death_sound": "minecraft:entity.pig.death",
        // 进食时播放的声音事件的注册表名称。
        "eat_sound": "minecraft:entity.pig.eat",
        // 受伤时播放的声音事件的注册表名称。
        "hurt_sound": "minecraft:entity.pig.hurt",
        // 踩踏时播放的声音事件的注册表名称。
        "step_sound": "minecraft:entity.pig.step"
    },
    // 实体年龄小于 0(幼年)时播放的声音。
    "baby_sounds": {
        "ambient_sound": "minecraft:entity.baby_pig.ambient",
        "death_sound": "minecraft:entity.baby_pig.death",
        "eat_sound": "minecraft:entity.baby_pig.eat",
        "hurt_sound": "minecraft:entity.baby_pig.hurt",
        "step_sound": "minecraft:entity.baby_pig.step"
    }
}

对于猫:

// 文件位于:
// - `data/examplemod/cat_sound_variant/example_cat_sound.json`
{
    // 实体年龄大于或等于 0(成年)时播放的声音。
    "adult_sounds": {
        // 驯服后空闲时随机播放的声音事件的注册表名称。
        "ambient_sound": "minecraft:entity.cat.ambient",
        // 未驯服且被食物诱惑时播放的声音事件的注册表名称。
        "beg_for_food_sound": "minecraft:entity.cat.beg_for_food",
        // 被杀死时播放的声音事件的注册表名称。
        "death_sound": "minecraft:entity.cat.death",
        // 被喂食时播放的声音事件的注册表名称。
        "eat_sound": "minecraft:entity.cat.eat",
        // 发出嘶嘶声时播放的声音事件的注册表名称,通常针对追逐的幻翼。
        "hiss_sound": "minecraft:entity.cat.hiss",
        // 受伤时播放的声音事件的注册表名称。
        "hurt_sound": "minecraft:entity.cat.hurt",
        // 发出呼噜声时播放的声音事件的注册表名称,通常在恋爱或躺下时。
        "purr_sound": "minecraft:entity.cat.purr",
        // 驯服后 25% 空闲时随机播放的声音事件的注册表名称。
        "purreow_sound": "minecraft:entity.cat.purreow",
        // 未驯服时空闲时随机播放的声音事件的注册表名称。
        "stray_ambient_sound": "minecraft:entity.cat.stray_ambient"
    },
    // 实体年龄小于 0(幼年)时播放的声音。
    "baby_sounds": {
        "ambient_sound": "minecraft:entity.baby_cat.ambient",
        "beg_for_food_sound": "minecraft:entity.baby_cat.beg_for_food",
        "death_sound": "minecraft:entity.baby_cat.death",
        "eat_sound": "minecraft:entity.baby_cat.eat",
        "hiss_sound": "minecraft:entity.baby_cat.hiss",
        "hurt_sound": "minecraft:entity.baby_cat.hurt",
        "purr_sound": "minecraft:entity.baby_cat.purr",
        "purreow_sound": "minecraft:entity.baby_cat.purreow",
        "stray_ambient_sound": "minecraft:entity.baby_cat.stray_ambient"
    }
}
  • net.minecraft.core.registries.Registries
    • CAT_SOUND_VARIANT - 猫应发出的声音的注册表键。
    • CHICKEN_SOUND_VARIANT - 鸡应发出的声音的注册表键。
    • COW_SOUND_VARIANT - 牛应发出的声音的注册表键。
    • PIG_SOUND_VARIANT - 猪应发出的声音的注册表键。
  • net.minecraft.network.synched.EntityDataSerializers
    • CAT_SOUND_VARIANT - 猫应发出的声音的实体序列化器。
    • CHICKEN_SOUND_VARIANT - 鸡应发出的声音的实体序列化器。
    • COW_SOUND_VARIANT - 牛应发出的声音的实体序列化器。
    • PIG_SOUND_VARIANT - 猪应发出的声音的实体序列化器。
  • net.minecraft.sounds.SoundEvents
    • CAT_* 声音现在是 Holder$Reference 或存储在 CAT_SOUNDS 映射中
    • CHICKEN_* 声音现在是 Holder$Reference 或存储在 CHICKEN_SOUNDS 映射中
    • COW_* 声音存储在 COW_SOUNDS 映射中
    • PIG_* 声音现在是 Holder$Reference 或存储在 PIG_SOUNDS 映射中
  • net.minecraft.world.entity.animal.chicken
    • ChickenSoundVariant - 鸡变体播放的声音。
    • ChickenSoundVariants - 所有原版鸡变体。
  • net.minecraft.world.entity.animal.cow
    • AbstractCow#getSoundSet - 获取牛发出的声音。
    • CowSoundVariant - 牛变体播放的声音。
    • CowSoundVariants - 所有原版牛变体。
  • net.minecraft.world.entity.animal.feline
    • CatSoundVariant - 猫变体播放的声音。
    • CatSoundVariants - 所有原版猫变体。
  • net.minecraft.world.entity.animal.chicken
    • ChickenSoundVariant - 鸡变体播放的声音。
    • ChickenSoundVariants - 所有原版鸡变体。
  • net.minecraft.world.entity.animal.pig
    • PigSoundVariant - 猪变体播放的声音。
    • PigSoundVariants - 所有原版猪变体。

音频变更

音频设备现在通过 DeviceTracker 处理,根据底层机器,允许机器在音频设备更改时发送系统事件,或使用标准轮询间隔重新查询可用设备列表。

  • com.mojang.blaze3d.audio
    • AbstractDeviceTracker - 用于管理音频设备更改的抽象跟踪器。
    • CallbackDeviceTracker - 使用 SOFT 系统事件回调确定更改的设备跟踪器。
    • DeviceList - 所有音频设备的列表,包括默认设备(如果可用)。
    • DeviceTracker - 用于管理音频设备更改的接口。
    • Library
      • NO_DEVICE 现在是 public 而不是 private
      • init 现在接受 DeviceList
      • getDefaultDeviceName 移至 DeviceList#defaultDevice
      • getCurrentDeviceName -> currentDeviceName
      • hasDefaultDeviceChanged 移至 AbstractDeviceTracker,不是一对一
      • getAvailableSoundDevices 移至 DeviceList,不是一对一
      • createDeviceTracker - 创建用于管理音频设备更改的跟踪器。
      • getDebugString -> getChannelDebugString
    • PollingDeviceTracker - 使用轮询间隔确定更改的设备跟踪器。
    • SoundBuffer
      • format - 声音流的格式。
      • size - 声音流中的字节数。
      • isValid - 声音流是否处于有效状态。
  • net.minecraft.client.Options
    • DEFAULT_SOUND_DEVICE 现在是 private 而不是 public
    • isSoundDeviceDefault - 检查设备是否为默认音频设备。
  • net.minecraft.client.gui.components.debug
    • DebugEntrySoundCache - 显示已加载声音流当前缓存的调试条目。
    • DebugScreenEntries#SOUND_CACHE - 声音流缓存调试信息的标识符。
  • net.minecraft.client.sounds
    • SoundBufferLibrary
      • enumerate - 循环所有缓存的声音,输出其 id、大小和格式。
      • $DebugOutput - 接受某些声音元数据的接口。
        • $Counter - 跟踪声音流数量和总大小的输出实现。
    • SoundEngine
      • getDebugString -> getChannelDebugString, getSoundCacheDebugStats; 不是一对一
      • $DeviceCheckState 已移除
    • SoundManager#getDebugString -> getChannelDebugString, getSoundCacheDebugStats; 不是一对一

输入消息编辑器支持

Minecraft 现在支持输入消息编辑器(IME),允许输入来自中文或印地语等语言的复杂字符,而不是临时的预编辑文本。预编辑文本在游戏内显示为覆盖层,而主机操作系统提供的任何其他 IME 功能。通过此添加,可以通过 GuiEventListener#preeditUpdated 在屏幕中添加支持,或使用实现该方法的现有原版小部件。

  • com.mojang.blaze3d.platform
    • InputConstants#setupKeyboardCallbacks 现在接受 GLFWCharCallbackI 而不是 GLFWCharModsCallbackI 用于字符键入回调,GLFWPreeditCallbackI 用于通过输入方法编辑器处理复杂字符输入,以及 GLFWIMEStatusCallbackI 用于通知编辑器的状态
    • MessageBox - 用于创建操作系统原生消息框的工具。
    • TextInputManager - 用于处理游戏窗口中文本输入的管理器。
      • setTextInputArea - 设置预测文本光标应出现的区域。
      • startTextInput, stopTextInput - 处理切换输入消息编辑器。
  • net.minecraft.client
    • KeyboardHandler
      • resubmitLastPreeditEvent - 重复发送的最后一个预编辑事件。
      • submitPreeditEvent - 告知监听器预编辑文本已更新。
    • Minecraft
      • textInputManager - 返回输入管理器。
      • onTextInputFocusChange - 根据文本输入是否聚焦更改编辑器输入状态。
  • net.minecraft.client.gui.GuiGraphics
    • setPreeditOverlay - 设置绘制预编辑文本的覆盖层。
    • renderDeferredElements 现在接受鼠标位置的 int 和游戏时间增量刻 float
  • net.minecraft.client.gui.components
    • IMEPreeditOverlay - 用于显示输入消息编辑器预编辑文本的覆盖层。
    • TextCursorUtils - 绘制文本光标的工具。
  • net.minecraft.client.gui.components.events.GuiEventListener#preeditUpdated - 监听预编辑文本何时更改。
  • net.minecraft.client.input
    • CharacterEvent 不再接受修饰符 int
    • PreeditEvent - 一个包含预编辑文本以及光标位置的事件。

炼药锅交互调度器

炼药锅的交互已进行了一些重组,所有注册已从 CauldronInteraction 移至 CauldronInteractions。此外,炼药锅类型的底层 $InteractionMap 已被 $Dispatcher 取代,它可以为标签和物品注册交互。标签在物品之前检查。

CauldronInteractions.EMPTY.put(
    // 要使用的物品或 TagKey
    ItemTags.WOOL,
    // 要应用的炼药锅交互
    (state, level, pos, player, hand, itemInHand) -> InteractionResult.TRY_WITH_EMPTY_HAND
);
  • net.minecraft.core.cauldron
    • CauldronInteraction
      • 所有关于将交互注册到映射的字段已移至 CauldronInteractions
        • INTERACTIONS -> CauldronInteractions#ID_MAPPER,现在是 private
      • DEFAULT - 与炼药锅的默认交互
      • $InteractionMap -> $Dispatcher,不是一对一
    • CauldronInteractions - 所有原版炼药锅交互。

基于规则的方块状态提供者

RuleBasedStateProvider 现在扩展了 BlockStateProvider,允许它在需要状态提供器的任何地方使用。其实现没有改变,现在只需要将 rule_based_state_provider 指定为 type。因此,所有使用 RuleBasedBlockStateProvider 的配置都已放宽,以允许任何 BlockStateProvider

  • net.minecraft.world.level.levelgen.feature.configurations
    • DiskConfiguration 现在接受一个 BlockStateProvider 而不是 RuleBasedBlockStateProvider
    • TreeConfiguration 现在接受一个 BlockStateProvider 而不是 RuleBasedBlockStateProvider
      • belowTrunkProvider 现在是 BlockStateProvider 而不是 RuleBasedBlockStateProvider
      • $TreeConfigurationBuilder 现在接受一个 BlockStateProvider 而不是 RuleBasedBlockStateProvider
  • net.minecraft.world.level.levelgen.feature.stateproviders
    • BlockStateProvider#getOptionalState - 获取方块的状态,否则为 null
    • BlockStateProviderType#RULE_BASED_STATE_PROVIDER - 基于规则的状态提供器的类型。
    • RuleBasedBlockStateProvider -> RuleBasedStateProvider,现在是一个类,实现 BlockStateProvider
      • 构造函数现在可以接受一个可空的回退 BlockStateProvider
      • ifTrueThenProvide - 如果谓词为真,则提供给定的方块。
      • simple -> always
      • $Builder - 用于构建放置方块规则的构建器。

流体逻辑重组

通用实体流体移动已移至单独的 EntityFluidInteraction 类中,其中所有跟踪的流体都会更新,然后在层时间可能被水流推动。

  • net.minecraft.world.entity
    • Entity
      • updateInWaterStateAndDoFluidPushing -> updateFluidInteraction,不是一对一
      • updateFluidHeightAndDoFluidPushing -> EntityFluidInteraction#update
      • getFluidInteractionBox - 获取实体在流体交互期间的边界框。
      • modifyPassengerFluidInteractionBox - 返回实体骑乘在某些交通工具中时修改后的边界框。
    • EntityFluidInteraction - 用于管理实体流体交互和基本移动的处理程序。
  • net.minecraft.world.level.chunk.LevelChunkSection#hasFluid - 区块部分是否包含流体方块。

移除随机斑块特征

随机斑块特征已被完全移除,转而使用像大多数其他特征一样的位置放置。要转换,配置中定义为 ConfiguredFeature 的部分应该是它自己的文件。然后,位置放置应指定 CountPlacement,后跟使用 TrapezoidIntRandomOffsetPlacement,最后是 BlockPredicateFilter

// 在 `data/examplemod/worldgen/configured_feature/example_configured_feature.json` 中
{
    // 之前 config.feature.feature
    "type": "minecraft:simple_block",
    "config": {
        "to_place": {
            "type": "minecraft:simple_state_provider",
            "state": {
                "Name": "minecraft:sweet_berry_bush",
                "Properties": {
                    "age": "3"
                }
            }
        }
    }
}

// 在 `data/examplemod/worldgen/placed_feature/example_placed_feature.json` 中
{
    "feature": "examplemod:example_configured_feature",
    "placement": [
        {
            // 之前 config.tries
            "type": "minecraft:count",
            "count": 96
        },
        {
            "type": "minecraft:random_offset",
            "xz_spread": {
                // 之前 config.xz_spread
                // min 和 max 是加法逆元
                "type": "minecraft:trapezoid",
                "max": 7,
                "min": -7,
                "plateau": 0
            },
            "y_spread": {
                // 之前 config.y_spread
                "type": "minecraft:trapezoid",
                "max": 3,
                "min": -3,
                "plateau": 0
            }
        },
        {
            // 之前 config.feature.placement
            // 这包含原始放置特征的位置放置
            "type": "minecraft:block_predicate_filter",
            "predicate": {
                "type": "minecraft:all_of",
                "predicates": [
                    {
                        "type": "minecraft:matching_block_tag",
                        "tag": "minecraft:air"
                    },
                    {
                        "type": "minecraft:matching_blocks",
                        "blocks": "minecraft:grass_block",
                        "offset": [ 0, -1, 0 ]
                    }
                ]
            }
        }
    ]
}
  • net.minecraft.data.worldgen.features
    • FeatureUtils#simpleRandomPatchConfiguration, simplePatchConfiguration 已移除
      • 通常被 Feature#SIMPLE_BLOCK 替换,带有随机偏移和过滤器的位置放置
    • NetherFeatures#PATCH_* 字段不再有 PATCH_* 前缀
    • VegetationFeatures
      • PATCH_* 字段不再有 PATCH_* 前缀
      • WILDFLOWERS_BIRCH_FOREST, WILDFLOWERS_MEADOW -> WILDFLOWER,不是一对一
      • PALE_FOREST_FLOWERS -> PALE_FOREST_FLOWER
  • net.minecraft.world.level.biome.BiomeGenerationSettings#getFlowerFeatures -> getBoneMealFeatures
  • net.minecraft.world.level.levelgen.feature
    • ConfiguredFeature#getFeatures -> getSubFeatures,现在返回一个持有者包装的 ConfiguredFeature 流,不包含此特征
    • Feature
      • FLOWER, NO_BONEMEAL_FLOWER 已移除
      • RANDOM_PATCH 已移除
    • RandomPatchFeature 类已移除
  • net.minecraft.world.level.levelgen.feature.configurations
    • FeatureConfiguration#getFeatures -> getSubFeatures,现在返回一个持有者包装的 ConfiguredFeature
    • RandomPatchConfiguration 记录已移除
  • net.minecraft.world.level.levelgen.placement.PlacedFeature#getFeatures 现在返回一个持有者包装的 ConfiguredFeature 流,并连接了此特征

特定逻辑变更

  • 画中画提交调用现在使用 0xF000F0 而不是 0x000000 作为光照坐标。
  • net.minecraft.client.multiplayer.RegistryDataCollector#collectGameRegistriesboolean 参数现在仅处理从同步注册表以及标签更新组件。
  • net.minecraft.client.renderer.RenderPipelines#VIGNETTE 现在将 alpha 与源为零和目标为一混合。
  • net.minecraft.server.packs.PathPackResources#getResource, listPath, listResources 使用标识符的命名空间首先解析路径。
  • net.minecraft.world.entity.EntitySelector#CAN_BE_PICKED 现在可以找到旁观者模式下的实体,假设 Entity#isPickable 为 true。
  • net.minecraft.world.entity.ai.sensing.NearestVisibleLivingEntitySensor#requires 默认不再实现。
  • net.minecraft.world.level.levelgen.WorldOptions#generate_features JSON 中的字段已重命名为 generate_structures 以匹配其 Java 字段名称。
  • net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate#ONLY_IN_AIR_PREDICATE 现在匹配空气标签而不是仅仅空气方块。
  • net.minecraft.world.level.timers
    • FunctionCallback, FunctionTagCallback 现在在序列化时使用 id 而不是 Name
    • TimerCallbacks 现在在序列化时使用 type 而不是 Type

数据组件新增

  • dye - 将物品设置为染料材料,在特定情况下使用。
  • additional_trade_cost - 按指定金额偏移交易成本的修饰符。
  • pig/sound_variant - 猪应发出的声音。
  • cow/sound_variant - 牛应发出的声音。
  • chicken/sound_variant - 鸡应发出的声音。
  • cat/sound_variant - 猫应发出的声音。

环境属性新增

  • visual/block_light_tint - 着色方块发出的光的颜色。
  • visual/night_vision_color - 夜视激活时的颜色。
  • visual/ambient_light_color - 环境中环境光的颜色。

标签更改

  • minecraft:block
    • bamboo_plantable_on -> supports_bamboo
    • mushroom_grow_block -> overrides_mushroom_light_requirement
    • small_dripleaf_placeable -> supports_small_dripleaf
    • big_dripleaf_placeable -> supports_big_dripleaf
    • dry_vegetation_may_place_on -> supports_dry_vegetation
    • snow_layer_cannot_survive_on -> cannot_support_snow_layer
    • snow_layer_can_survive_on -> support_override_snow_layer
    • enables_bubble_column_drag_down
    • enables_bubble_column_push_up
    • supports_vegetation
    • supports_crops
    • supports_stem_crops
    • supports_stem_fruit
    • supports_pumpkin_stem
    • supports_melon_stem
    • supports_pumpkin_stem_fruit
    • supports_melon_stem_fruit
    • supports_sugar_cane
    • supports_sugar_cane_adjacently
    • supports_cactus
    • supports_chorus_plant
    • supports_chorus_flower
    • supports_nether_sprouts
    • supports_azalea
    • supports_warped_fungus
    • supports_crimson_fungus
    • supports_mangrove_propagule
    • supports_hanging_mangrove_propagule
    • supports_nether_wart
    • supports_crimson_roots
    • supports_warped_roots
    • supports_wither_rose
    • supports_cocoa
    • supports_lily_pad
    • supports_frogspawn
    • support_override_cactus_flower
    • cannot_support_seagrass
    • cannot_support_kelp
    • grows_crops
    • mud
    • moss_blocks
    • grass_blocks
    • substrate_overworld
    • beneath_tree_podzol_replaceable
    • beneath_bamboo_podzol_replaceable
    • cannot_replace_below_tree_trunk
    • ice_spike_replaceable
    • forest_rock_can_place_on
    • huge_brown_mushroom_can_place_on
    • huge_red_mushroom_can_place_on
    • prevents_nearby_leaf_decay
  • minecraft:enchantment
    • trades/desert_special 已移除
    • trades/jungle_special 已移除
    • trades/plains_special 已移除
    • trades/savanna_special 已移除
    • trades/snow_special 已移除
    • trades/swamp_special 已移除
    • trades/taiga_special 已移除
  • minecraft:entity_type
    • cannot_be_age_locked
  • minecraft:fluid
    • supports_sugar_cane_adjacently
    • supports_lily_pad
    • supports_frogspawn
    • bubble_column_can_occupy
  • minecraft:item
    • metal_nuggets
    • dyeable 已移除,拆分为:
      • dyes
      • loom_dyes
      • loom_patterns
      • cauldron_can_remove_due
      • cat_collar_dyes
      • wolf_collar_dyes
    • mud
    • moss_blocks
    • grass_blocks
  • minecraft:potion
    • tradable
  • minecraft:worldgen/configured_feature
    • can_spawn_from_bone_meal

添加列表

  • net.minecraft.advancements.criterion
    • FoodPredicate - 可以检查食物水平和饱和度的标准谓词。
    • MinMaxBounds
      • validateContainedInRange - 返回一个验证目标范围并将结果作为数据结果返回的函数。
      • $Bounds#asRange - 将边界转换为 Range
  • net.minecraft.client
    • Minecraft#sendLowDiskSpaceWarning - 发送系统通知以提示磁盘空间不足。
    • Options#keyDebugLightmapTexture - 显示光照图纹理的键映射。
  • net.minecraft.client.gui.components
    • AbstractScrollArea
      • scrollbarWidth - 滚动条的宽度。
      • defaultSettings - 根据滚动速率构建默认滚动条设置。
      • $ScrollbarSettings - 包含滚动条元数据的记录。
    • DebugScreenOverlay
      • showLightmapTexture - 是否在覆盖层上渲染光照图纹理。
      • toggleLightmapTexture - 切换是否应渲染光照图纹理。
    • ScrollableLayout
      • setMinHeight - 设置容器布局的最小高度。
      • $ReserveStrategy - 在布局内保留滚动条宽度时使用的策略。
    • Tooltip
      • component - 要显示的工具提示的组件。
      • style - 用于计算工具提示背景和框架的标识符。
  • net.minecraft.client.gui.components.debug
    • DebugEntryDetailedMemory - 显示详细内存使用情况的调试条目。
    • DebugEntryLookingAt#getHitResult - 获取相机实体的命中结果。
    • DebugEntryLookingAtEntityTags - 用于显示实体标签的调试条目。
    • DebugScreenEntries
      • DETAILED_MEMORY - 详细内存使用调试条目的标识符。
      • LOOKING_AT_ENTITY_TAGS - 实体标签调试条目的标识符。
  • net.minecraft.client.gui.navigation.FocusNavigationEvent$ArrowNavigation#with - 设置导航的上一个焦点。
  • net.minecraft.client.gui.screens.GenericWaitingScreene#createWaitingWithoutButton - 创建一个不显示取消按钮的等待屏幕。
  • net.minecraft.client.gui.screens.options
    • DifficultyButtons - 一个包含创建难度按钮的布局元素的类。
    • HasGamemasterPermissionReaction - 标记选项屏幕能够响应游戏管理员权限更改的接口。
    • OptionsScreen#getLastScreen - 返回导航到此屏幕的上一个屏幕。
    • WorldOptionsScreen - 包含玩家所在当前世界的选项的屏幕。
  • net.minecraft.client.gui.screens.worldselection.EditWorldScreen#conditionallyMakeBackupAndShowToast - 仅在传入的 boolean 为 true 时制作备份并显示提示;否则返回一个 false 的 future。
  • net.minecraft.client.multiplayer.MultiPlayerGameMode#spectate - 向服务器发送数据包,表示玩家将旁观给定的实体。
  • net.minecraft.client.multiplayer.prediction.BlockStatePredictionHandler#onTeleport - 当玩家在服务器上移动时运行,通常来自某种传送(例如命令、骑乘实体)。
  • net.minecraft.client.renderer
    • LightmapRenderStateExtractor - 提取光照图的渲染状态。
    • UiLightmap - 用户界面中的光照图。
    • RenderPipelines
      • LINES_DEPTH_BIAS - 一个将多边形深度偏移因子设置为 -1 并将单位设置为 -1 的渲染管线。
      • ENTITY_CUTOUT_DISSOLVE - 一个使用蒙版采样器将实体模型溶解到背景中的渲染管线。
  • net.minecraft.client.renderer.rendertype.RenderType#hasBlending - 管线是否定义了混合函数。
  • net.minecraft.commands.ArgumentVisitor - 用于访问命令参数的辅助类。
  • net.minecraft.commands.arguments.selector.EntitySelector#COMPILABLE_CODEC - 包装在 EntitySelectorParser 周围的 CompilableString 编解码器。
  • net.minecraft.core.component.predicates
    • DataComponentPredicates#VILLAGER_VARIANT - 检查村民类型的谓词。
    • VillagerTypePredicate - 检查村民类型的谓词。
  • net.minecraft.core.dispenser.SpawnEggItemBehavior - 刷怪蛋的发射器行为。
  • net.minecraft.core.registries.ConcurrentHolderGetter - 从本地缓存读取引用的获取器,必要时同步到原始数据。
  • net.minecraft.data
    • BlockFamilies
      • END_STONE - 末地石变体的家族。
      • getFamily - 获取基础方块的家族(如果存在)。
    • BlockFamily
      • $Builder#tiles, $Variant#TILES - 作为某个基础方块的瓷砖变体的方块。
      • $Builder#bricks, $Variant#BRICKS - 作为某个基础方块的砖块变体的方块。
      • $Builder#cobbled, $Variant#COBBLED - 作为某个基础方块的圆石变体的方块。
    • DataGenerator$Uncached - 不缓存任何关于生成文件信息的数据生成器。
  • net.minecraft.data.recipes.RecipeProvider
    • bricksBuilder, tilesBuilder - 用于砖块和瓷砖方块变体的构建器。
    • generateCraftingRecipe, generateStonecutterRecipe - 为给定的方块家族生成适当的配方。
    • getBaseBlock -> getBaseBlockForCrafting
    • bredAnimal - 如果玩家已使两只动物繁殖,则解锁配方。
  • net.minecraft.gametest.framework
    • GameTestEvent#createWithMinimumDelay - 创建一个具有最小延迟的测试事件。
    • GameTestHelper
      • getBoundsWithPadding - 获取带有指定填充的测试区域的边界框。
      • runBeforeTestEnd - 在测试结束前一 tick 运行 runnable。
      • despawnItem - 清除位置距离内的所有物品实体。
      • discard - 丢弃实体。
      • setTime - 设置维度默认时钟的时间。
      • placeBlock - 在相对位置和方向上放置给定的方块。
    • GameTestInstance#padding - 每个游戏测试周围间隔的方块数。
    • GameTestSequence#thenWaitAtLeast - 在运行 runnable 之前至少等待指定的 tick 数。
  • net.minecraft.nbt.TextComponentTagVisitor
    • $PlainStyling - 将 nbt 存储在组件字面量映射中的样式。
    • $RichStyling - 带有语法高亮和格式化的 nbt 样式。
    • $Styling - 定义读取标签应如何样式的接口。
    • $Token - 用于更丰富地表示标签数据的令牌。
  • net.minecraft.network.chat.ResolutionContext - 组件被解析为字符串的上下文。
  • net.minecraft.network.chat.contents.NbtContents#NBT_PATH_CODEC - 包装在 NbtPathArgument$NbtPath 周围的 CompilableString 编解码器。
  • net.minecraft.network.chat.contents.data.BlockDataSource#BLOCK_POS_CDEC - 包装在 Coordinates 周围的 CompilableString 编解码器。
  • net.minecraft.network.protocol.game
    • ClientboundGameRuleValuesPacket - 以字符串形式向客户端发送游戏规则值的数据包。
    • ClientboundGamePacketListener#handleGameRuleValues - 处理从服务器发送的游戏规则值。
    • ClientboundLowDiskSpaceWarningPacket - 发送给客户端警告机器磁盘空间不足的数据包。
    • ClientGamePacketListener#handleLowDiskSpaceWarning - 处理关于磁盘空间不足的警告数据包。
    • ServerboundAttackPacket - 发送给服务器关于玩家攻击了哪个实体的数据包。
    • ServerboundClientCommandPacket$Action#REQUEST_GAMERULE_VALUES - 从服务器请求游戏规则值。
    • ServerboundSetGameRulePacket - 从客户端发送设置游戏规则条目的数据包。
    • ServerboundSpectateEntityPacket - 发送给服务器关于玩家想要旁观哪个实体的数据包。
    • ServerGamePacketListener
      • handleAttack - 处理玩家对实体的攻击。
      • handleSpectateEntity - 处理玩家想要旁观实体。
      • handleSetGameRule - 处理从客户端设置游戏规则。
  • net.minecraft.resources
    • FileToIdConverter#extensionMatches - 检查标识符是否以指定的扩展名结尾。
    • Identifier
      • ALLOWED_NAMESPACE_CHARACTERS - 标识符命名空间中允许的字符。
      • resolveAgainst - 通过检查 /<namespace>/<path> 从给定根解析路径。
  • net.minecraft.server
    • Bootstrap#shutdownStdout - 关闭 stdout 流。
    • MinecraftServer
      • DEFAULT_GAME_RULES - 服务器的默认游戏规则。
      • warnOnLowDiskSpace - 如果磁盘空间低于 64 MiB,则发送警告。
      • sendLowDiskSpaceWarning - 发送磁盘空间不足的警告。
  • net.minecraft.server.commands.SwingCommand - 调用所有目标的 LivingEntity#swing 的命令。
  • net.minecraft.server.level.ServerPlayer
    • sendBuildLimitMessage - 如果玩家在相应的 Y 方向上无法再建造,则发送覆盖消息。
    • sendSpawnProtectionMessage - 如果玩家因生成保护而无法修改地形,则发送覆盖消息。
  • net.minecraft.server.packs.AbstractPackResources#loadMetadata - 加载根目录的 pack.mcmeta
  • net.minecraft.server.packs.resources.ResourceMetadata$MapBased - 将节存储在映射中的资源元数据。
  • net.minecraft.tags.TagLoader$ElementLookup#fromGetters - 根据元素是否需要,从给定的 HolderGetter 构造元素查找。
  • net.minecraft.util
    • ARGB#gray - 根据给定的亮度获取灰度颜色。
    • CompilableString - 用于获取某些字符串模式并通过某些解析器将其编译为对象的工具。
    • LightCoordsUtil - 用于从光照值确定光照坐标的工具。
    • ProblemReporter$MapEntryPathElement - 映射中某个条目的路径元素。
    • Util#allOfEnumExcept - 获取除提供的值之外的所有枚举的集合。
  • net.minecraft.util.thread.BlockableEventLoop#hasDelayedCrash - 是否有排队的崩溃报告。
  • net.minecraft.util.valueproviders.TrapezoidInt - 使用梯形分布采样随机值。
  • net.minecraft.world.InteractionHand#STREAM_CODEC - 交互手的网络编解码器。
  • net.minecraft.world.attribute
    • AttributeType#toFloat - 将属性值作为 float 获取,如果未定义则抛出异常。
    • AttributeTypes#INTEGER - 一个整数属性类型。
    • LerpFunction#ofInteger - 用于整数值的 lerp 函数。
  • net.minecraft.world.attribute.modifier
    • AttributeModifier#INTEGER_LIBRARY - 用于整数的操作符库。
    • IntegerModifier - 将某些参数应用于整数值的修饰符。
  • net.minecraft.world.entity
    • AgeableMob
      • AGE_LOCK_COOLDOWN_TICKS - 在实体可以年龄锁定/解锁之前等待的 tick 数。
      • ageLockParticleTimer - 年龄锁定/解锁时显示粒子的时间。
    • Entity
      • applyEffectsFromBlocksForLastMovements - 对实体应用上一次移动的方块效果,由物品使用。
      • $Flags - 一个注解,标记特定值为实体的标志位集。
    • LivingEntity#getLiquidCollisionShape - 返回实体尝试与液体碰撞时的边界。
    • Mob
      • asValidTarget - 检查实体是否为该实体的有效目标(可以攻击)。
      • getTargetUnchecked - 获取原始目标而不检查其有效性。
      • canAgeUp - 实体是否可以成长为更成熟的变体。
      • setAgeLocked, isAgeLocked - 实体是否不能成长。
    • NeutralMob#getTargetUnchecked - 获取原始目标而不检查其有效性。
    • TamableAnimal#feed - 玩家将物品作为食物给予,根据存储的组件或某些默认值治愈它们。
  • net.minecraft.world.entity.ai.behavior
    • BehaviorControl#getRequiredMemories - 行为所需的记忆列表。
    • GoAndGiveItemsToTarget$ItemThrower - 一个处理如果因该实体的行为而抛出物品时应发生什么的接口。
  • net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder$TriggerWithResult#memories - 行为所需的记忆列表。
  • net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities#nearbyEntities - 在该实体的跟随范围内的实体列表。
  • net.minecraft.world.entity.decoration.LeashFenceKnotEntity
    • getKnot - 在给定位置找到结,否则返回空的可选值。
    • createKnot - 创建一个新结并将其添加到关卡中。
  • net.minecraft.world.entity.monster.piglin
    • PiglinAi
      • MAX_TIME_BETWEEN_HUNTS - 猪灵再次开始狩猎前的最大秒数。
      • findNearbyAdultPiglins - 返回此猪灵记忆中所有成年猪灵的列表。
  • net.minecraft.world.entity.raid.Raid
    • getBannerComponentPatch - 获取旗帜图案的组件。
    • getOminousBannerTemplate - 获取不祥旗帜的堆叠模板。
  • net.minecraft.world.inventory.SlotRanges
    • MOB_INVENTORY_SLOT_OFFSET - 生物物品栏的起始索引。
    • MOB_INVENTORY_SIZE - 生物物品栏的大小。
  • net.minecraft.world.item.component.BundleContents#BEEHIVE_WEIGHT - 蜂箱的重量。
  • net.minecraft.world.item.enchantment.EnchantmentTarget#NON_DAMAGE_CODEC - 仅允许攻击者和受害者附魔目标的编解码器。
  • net.minecraft.world.level.block.BigDripleafBlock#canGrowInto - 大垂滴叶是否可以生长到指定位置。
  • net.minecraft.world.level.block.grower.TreeGrower#getMinimumHeight - 如果存在,获取树干放置器的基本高度。
  • net.minecraft.world.level.block.state
    • BlockBehaviour$PostProcess - 一个获取要标记为后处理的位置的接口。
    • StateDefinition
      • propertiesCodec - 状态属性的映射编解码器。
      • isSingletonState - 定义是否只包含一个状态。
    • StateHolder#isSingletonState - 持有者是否只包含一个状态。
  • net.minecraft.world.level.block.state.properties
    • NoteBlockInstrument
      • TRUMPET - 铜块放置在音符盒下时发出的声音。
      • TRUMPET_EXPOSED - 斑驳的铜块放置在音符盒下时发出的声音。
      • TRUMPET_OXIDIZED - 氧化的铜块放置在音符盒下时发出的声音。
      • TRUMPET_WEATHERED - 锈蚀的铜块放置在音符盒下时发出的声音。
    • Property$Value#valueName - 获取值的名称。
  • net.minecraft.world.level.dimension.DimensionDefaults
    • BLOCK_LIGHT_TINT - 方块光的默认着色。
    • NIGHT_VISION_COLOR - 夜视激活时的默认颜色。
    • TURTLE_EGG_HATCH_CHANCE - 海龟蛋在随机 tick 中孵化的几率。
  • net.minecraft.world.level.gamerules.GameRule#getIdentifierWithFallback - 获取游戏规则的标识符,否则获取未注册的标识符。
  • net.minecraft.world.level.levelgen
    • NoiseBasedChunkGenerator#getInterpolatedNoiseValue - 获取给定位置的插值密度,如果 Y 超出噪声设置范围,则返回非数字值。
    • NoiseChunk#getInterpolatedDensity - 计算完整的噪声密度。
  • net.minecraft.world.level.levelgen.feature.AbstractHugeMushroomFeature#MIN_MUSHROOM_HEIGHT - 蘑菇的最小高度。
  • net.minecraft.world.level.levelgen.feature.configurations.BlockBlobConfiguration - 块团块特征的配置。
  • net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacer#getBaseHeight - 返回树干的最小高度。
  • net.minecraft.world.level.levelgen.placement.RandomOffsetPlacement#ofTriangle - 创建一个梯形分布,用于选择 XZ 和 Y 范围。
  • net.minecraft.world.level.material
    • FluidState#isFull - 流体量是否为八。
    • LavaFluid#LIGHT_EMISSION - 熔岩流体发出的光量。
  • net.minecraft.world.level.pathfinder.PathType#BIG_MOBS_CLOSE_TO_DANGER - 对于实体宽度大于一个方块的生物的路径惩罚。
  • net.minecraft.world.level.storage.LevelStorageSource#writeWorldGenSettings - 将世界生成设置写入其保存数据位置。
  • net.minecraft.world.level.storage.loot.functions
    • EnchantRandomlyFunction$Builder#withOptions - 指定可用于随机附魔此物品的附魔。
    • SetRandomDyesFunction - 一个物品函数,从提供的列表中应用随机染料(如果物品在 dyeable 标签中)到 DYED_COLOR 组件。
    • SetRandomPotionFunction - 一个物品函数,从提供的列表中应用随机药水到 POTION_CONTENTS 组件。
  • net.minecraft.world.level.storage.loot.parameters.LootContextParams#ADDITIONAL_COST_COMPONENT_ALLOWED - 允许交易在所需堆叠或修饰符需要时产生额外成本。
  • net.minecraft.world.level.storage.loot.predicates.EnvironmentAttributeCheck - 检查给定属性是否与提供的值匹配的战利品条件。
  • net.minecraft.world.level.storage.loot.providers.number
    • EnvironmentAttributeValue - 以浮点数形式获取属性值的提供器。
    • Sum - 对所有提供的数字提供器的值求和的提供器。
  • net.minecraft.world.phys.AABB$Builder#isDefined - 检查是否至少有一个点构成边界框。

更改列表

  • net.minecraft.advancements.criterion
    • EntityTypePredicate#matches 现在接受一个持有者包装的 EntityType 而不是原始类型本身
    • KilledTrigger$TriggerInstance#entityPredicate -> entity
    • PlayerPredicate 现在接受一个 FoodPredicate
      • 可以使用 PlayerPredicate$Builder#setFood 设置
  • net.minecraft.client.gui
    • GuiGraphics
      • blit 现在有一个接受 GpuTextureViewGpuSampler 的重载
      • setTooltipForNextFrame 现在有一个接受工具提示的 FormattedCharSequence 列表以及是否替换任何现有工具提示的重载
    • ItemSlotMouseAction#onSlotClicked 现在接受一个 ContainerInput 而不是 ClickType
  • net.minecraft.client.gui.components
    • AbstractContainerWidget 现在接受一个 AbstractScrollArea$ScrollbarSettings
    • AbstractScrollArea 现在接受一个 AbstractScrollArea$ScrollbarSettings
      • scrollbarVisible -> scrollable
      • scrollBarY 现在是 public
      • scrollRate 不再是抽象的
    • AbstractTextAreaWidget 现在接受一个 AbstractScrollArea$ScrollbarSettings
    • PopupScreen$Builder#setMessage -> addMessage,不是一对一
    • ScrollableLayout$Container 现在接受一个 AbstractScrollArea$ScrollbarSettings
    • Tooltip#create 现在有一个接受可选的 TooltipComponent 和样式 Identifier 的重载
  • net.minecraft.client.gui.components.debug
    • DebugEntryLookingAtBlock, DebugEntryLookingAtFluid -> DebugEntryLookingAt
      • 更具体地说,$BlockStateInfo, $BlockTagInfo, $FluidStateInfo, $FluidTagInfo
    • DebugEntryLookingAtEntity#GROUP 现在是 public
    • DebugScreenEntries
      • LOOKING_AT_BLOCK -> LOOKING_AT_BLOCK_STATE, LOOKING_AT_BLOCK_TAGS
      • LOOKING_AT_FLUID -> LOOKING_AT_FLUID_STATE, LOOKING_AT_FLUID_TAGS
    • DebugScreenEntryList 现在接受一个 DataFixer
  • net.minecraft.client.gui.components.tabs.TabNavigationBar#setWidth -> updateWidth,不是一对一
  • net.minecraft.client.gui.navigation.FocusNavigationEvent$ArrowNavigation 现在接受一个可空的 ScreenRectangle 用于上一个焦点
  • net.minecraft.client.gui.screens
    • ConfirmScreen#layout 现在是 final
    • DemoIntroScreenClientPacketListener#openDemoIntroScreen 取代,现在是 private
    • GenericWaitingScreen 现在接受三个 boolean,分别表示是否显示加载点、取消按钮以及屏幕是否应在按下 ESC 时关闭
  • net.minecraft.client.gui.screens.inventory.AbstractMountInventoryScreen#mount 现在是 final
  • net.minecraft.client.gui.screens.options
    • OptionsScreen 现在实现 HasGamemasterPermissionReaction
      • 构造函数现在接受一个 boolean 表示玩家是否当前在世界中
      • createDifficultyButton 现在在 WorldOptionsScreen#createDifficultyButtons 中处理,不是一对一
    • WorldOptionsScreen 现在实现 HasGamemasterPermissionReaction
      • createDifficultyButtons -> DifficultyButtons#create,现在是 public
  • net.minecraft.client.multiplayer
    • ClientLevel#syncBlockState 现在可以接受一个可空的玩家位置
    • MultiPlayerGameMode#handleInventoryMouseClick 现在接受一个 ContainerInput 而不是 ClickType
    • WeatherEffectRenderer#render 不再接受 MultiBufferSource
  • net.minecraft.client.renderer.block.ModelBlockRenderer$Cache#getLightColor -> getLightCoords
  • net.minecraft.client.renderer.blockentity.state
    • BrushableBlockRenderState#itemState 现在是 final
    • EndPortalRenderState 现在是一个 final 的 Direction 集而不是 EnumSet
    • ShelfRenderState#items 现在是 final
  • net.minecraft.client.renderer.entity.state
    • FallingBlockRenderState#movingBlockRenderState 现在是 final
    • HumanoidRenderState#attackArm -> ArmedEntityRenderState#attackArm
    • WitherRenderState#xHeadRots, yHeadRots 现在是 final
  • net.minecraft.client.resources.sounds.AbstractSoundInstance#random 现在是 final
  • net.minecraft.commands.SharedSuggestionProvider#getCustomTabSugggestions -> getCustomTabSuggestions
  • net.minecraft.commands.arguments.ComponentArgument#getResolvedComponent 现在接受一个非空的 Entity
  • net.minecraft.commands.arguments.selector.SelectorPatternCompilableString 取代
  • net.minecraft.core.HolderGetter$Provider#get, getOrThrow 现在有接受 TagKey 的重载
  • net.minecraft.data
    • BlockFamily
      • shouldGenerateRecipe -> shouldGenerateCraftingRecipe, shouldGenerateStonecutterRecipe
      • $Builder#dontGenerateRecipe -> dontGenerateCraftingRecipe, generateStonecutterRecipe
    • DataGenerator 现在是抽象的
      • 构造函数现在只接受 Path 输出,不接受 WorldVersion 或是否总是生成
        • 原始实现可以在 DataGenerator$Cached 中找到
      • run 现在是抽象的
    • Main#addServerProviders -> addServerDefinitionProviders,不再接受 dev boolean,不是一对一
    • 其余逻辑已放入 addServerConverters,接受 dev boolean 但不接受报告 boolean
  • net.minecraft.data.loot.BlockLootSubProvider
    • explosionResistant 现在是 private
    • enabledFeatures 现在是 private
    • map 现在是 private
  • net.minecraft.data.recipes
    • RecipeProvider$FamilyRecipeProvider -> $FamilyCraftingRecipeProvider, $FamilyStonecutterRecipeProvider
    • SingleItemRecipeBuilder#stonecutting 移至 BlockFamily 上的参数
  • net.minecraft.data.structures.SnbtToNbt 现在有一个接受单个输入文件夹路径的重载
  • net.minecraft.gametest.framework
    • GameTestHelper
      • assertBlockPresent 现在有一个只接受要检查的块的重载
      • moveTo 现在有接受 BlockPosVec3 作为位置的重载
      • assertEntityInstancePresent 现在有一个通过 double 膨胀边界框以检查内部实体的重载
    • GameTestServer#create 现在接受一个 int 表示运行所有匹配测试的次数
    • StructureUtils#testStructuresDir 拆分为 testStructuresTargetDir, testStructuresSourceDir
    • TestData 现在接受一个 int 表示测试周围填充的方块数
  • net.minecraft.nbt
    • NbtUtils
      • addDataVersion 现在使用泛型 Dynamic 而不是显式的 nbt 标签
      • getDataVersion 现在有一个默认值为 -1 的重载(如果未指定版本)
    • TextComponentTagVisitor 现在可以接受一个 $Styling 和一个 boolean 表示是否对键进行排序
      • handleEscapePretty 现在是一个 private 实例方法,而不是 protected static
  • net.minecraft.network.FriendlyByteBuf
    • readVec3, writeVec3Vec3#STREAM_CODEC 取代
    • readLpVec3, writeLpVec3Vec3#LP_STREAM_CODEC 取代
  • net.minecraft.network.chat
    • Component
      • nbt 现在接受一个 CompilableString 而不是 String
      • object 现在有一个接受 Component 回退的重载
    • ComponentContents#resolve 现在接受一个 ResolutionContext 而不是 CommandSourceStackEntity
    • ComponentUtils#updateForEnttiy -> resolve,接受 ResolutionContext 而不是 CommandSourceStackEntity
    • LastSeenMessages#EMPTY 现在是 final
  • net.minecraft.network.chat.contents
    • NbtContents 现在是一个记录,构造函数接受一个 CompilableString 而不是 String
    • ObjectContents 现在接受一个可选的 Component 作为回退,如果其内容无法验证
  • net.minecraft.network.chat.contents.data
    • BlockDataSource 现在接受一个 CompilableString 用于 Coordinates,而不是模式和编译后的位置
    • EntityDataSource 现在接受一个 CompilableString 用于 EntitySelector,而不是模式和编译后的选择器
  • net.minecraft.network.chat.contents.objects.ObjectInfo#description -> defaultFallback
  • net.minecraft.network.protocol.game
    • ClientboundSetEntityMotionPacket 现在是一个记录
    • ServerboundContainerClickPacket 现在接受一个 ContainerInput 而不是 ClickType
    • ServerboundInteractPacket 现在是一个记录,现在接受交互位置的 Vec3
  • net.minecraft.references
    • Blocks -> BlockIds
    • Items -> ItemIds
  • net.minecraft.resources
    • FileToIdConverter 现在是一个记录
    • RegistryDataLoader#load 现在返回一个 CompletableFuture 的冻结注册表访问
  • net.minecraft.server.MinecraftServer 现在接受一个 boolean 表示是否传播崩溃,通常用于抛出延迟崩溃
    • throwIfFatalException -> BlockableEventLoop#throwDelayedException,现在是 private,不是一对一
    • setFatalException -> BlockableEventLoop#delayCrash, relayDelayCrash;不是一对一
  • net.minecraft.server.commands.ChaseCommand#DIMENSION_NAMES 现在是 final
  • net.minecraft.server.dedicated.DedicatedServerProperties#acceptsTransfers 现在是 final
  • net.minecraft.server.packs
    • BuiltInMetadata 已合并到 ResourceMetadata
      • get -> ResourceMetadata#getSection
      • of -> ResourceMetadata#of
    • PathPackResources#getNamespaces 现在有一个接受根目录 Path 的静态重载
    • VanillaPackResourcesBuilder#setMetadata 现在接受一个 ResourceMetadata 而不是 BuiltInMetadata
  • net.minecraft.server.players.OldUsersConverter#serverReadyAfterUserconversionareOldUserListsRemoves 取代,现在是 public
  • net.minecraft.tags.TagLoader
    • loadTagsFromNetwork 现在接受一个 Registry 而不是 WritableRegistry,返回标签键到持有者条目列表的映射
    • loadTagsForRegistry 现在有一个接受注册表键以及元素查找的重载,返回标签键到持有者条目列表的映射
  • net.minecraft.util
    • Brightness
      • pack -> LightCoordsUtil#pack
      • block -> LightCoordsUtil#block
      • sky -> LightCoordsUtil#sky
    • RandomSource#createNewThreadLocalInstance -> createThreadLocalInstance
      • 现在有一个指定种子的重载
    • Util#copyAndAdd 现在有一个接受可变参数元素的重载
  • net.minecraft.util.thread
    • BlockableEventLoop 现在接受一个 boolean 表示是否传播崩溃,通常用于抛出延迟崩溃
    • ReentrantBlockableEventLoop 现在接受一个 boolean 表示是否传播崩溃,通常用于抛出延迟崩溃
  • net.minecraft.world.InteractionResult$ItemContext#NONE, DEFAULT 现在是 final
  • net.minecraft.world.attribute
    • AttributeType 现在接受一个 ToFloatFunction 用于数字提供器
      • ofInterpolated 现在接受一个 ToFloatFunction
    • EnvironmentAttributeReader#getValue 现在有一个接受 LootContext 的重载
  • net.minecraft.world.entity
    • Avatar 现在是抽象的
    • Entity
      • fluidHeight 现在是 final
      • getTags -> entityTags
      • getRandomY 现在有一个指定扩展 double 的重载
    • Leashable$Wrench#ZERO 现在是 final
    • LivingEntity
      • interpolation 现在是 final
      • swingingArm 现在是可空的
      • canAttackType -> canAttack,不是一对一,接受 LivingEntity 而不是 EntityType
      • lungeForwardMaybe -> postPiercingAttack
      • entityAttackRange -> getAttackRangeWith,现在接受用于攻击的 ItemStack
  • net.minecraft.world.entity.ai.behavior
    • GoAndGiveItemsToTarget 现在接受 $ItemThrower
      • throwItem -> BehaviorUtils#throwItem,不是一对一
    • SpearAttack 不再接受接近距离 float
    • TryLaySpawnOnWaterNearLand -> TryLaySpawnOnFluidNearLand,不是一对一
  • net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder#sequence 现在接受一个 Oneshot 作为第二个条目,而不是 Trigger
  • net.minecraft.world.entity.ai.goal
    • BoatGoals -> FollowPlayerRiddenEntityGoal$FollowEntityGoal
      • BOATENTITY 取代
    • FollowBoatGoal -> FollowPlayerRiddenEntityGoal,不是一对一
  • net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal#targetConditions 现在是 final
  • net.minecraft.world.entity.ai.sensing.NearestVisibleLivingEntitySensor#getMemory -> getMemoryToSet
  • net.minecraft.world.entity.decoration.Mannequin#getProfile -> Avatar#getProfile,现在是 publicabstract
    • 仍在 Mannequin 中实现
  • net.minecraft.world.entity.item.ItemEntity#DEFAULT_HEALTH 现在是 public 而不是 private
  • net.minecraft.world.entity.monster.breeze.Breeze#idle, slide, slideBack, longJump, shoot, inhale 现在是 final
  • net.minecraft.world.entity.monster.piglin.PiglinAi#isZombified 现在接受 Entity 而不是 EntityType
  • net.minecraft.world.entity.monster.warden.Warden#roarAnimationState, sniffAnimationState, emergeAnimationState, diggingAnimationState, attackAnimationState, sonicBoomAnimationState 现在是 final
  • net.minecraft.world.entity.monster.zombie.Zombie#handleAttributes 现在接受 EntitySpawnReason
  • net.minecraft.world.entity.player
    • Input#EMPTY 现在是 final
    • Player
      • currentImpulseImpactPos -> LivingEntity#currentImpulseImpactPos
      • currentExplosionCause -> LivingEntity#currentExplosionCause
      • setIgnoreFallDamageFromCurrentImpulse -> LivingEntity#setIgnoreFallDamageFromCurrentImpulse
      • applyPostImpulseGraceTime -> LivingEntity#applyPostImpulseGraceTime
      • isIgnoringFallDamageFromCurrentImpulse -> LivingEntity#isIgnoringFallDamageFromCurrentImpulse
      • tryResetCurrentImpulseContext -> LivingEntity#tryResetCurrentImpulseContext
      • resetCurrentImpulseContext -> LivingEntity#resetCurrentImpulseContext
      • isInPostImpulseGraceTime -> LivingEntity#isInPostImpulseGraceTime
      • isWithinAttackRange 现在接受用于攻击的 ItemStack
  • net.minecraft.world.entity.vehicle.minecart.NewMinecartBehavior$MinecartStep#EMPTY 现在是 final
  • net.minecraft.world.inventory.AbstractContainerMenu#getQuickCraftPlaceCount 现在接受快速制作槽位的数量而不是槽位集本身
  • net.minecraft.world.item
    • BundleItem#getSelectedItem -> getSelectedItemIndex
    • CreativeModeTab$Output 现在是 protected 而不是 public
    • EnderpearlItem#PROJECTILE_SHOOT_POWER 现在是 final
    • Item$Properties#requiredFeatures 现在有一个接受 FeatureFlagSet 的重载
    • Items#register* 方法现在是 private 而不是 public
    • ItemUtils#onContainerDestroyed 现在接受一个 StreamItemStack 而不是 Iterable
    • SignApplicator#tryApplyToSign, canApplyToSign 现在接受正在使用的 ItemStack
    • SnowballItem#PROJECTILE_SHOOT_POWER 现在是 final
    • ThrowablePotionItem#PROJECTILE_SHOOT_POWER 现在是 final
    • WindChargeItem#PROJECTILE_SHOOT_POWER 现在是 final
  • net.minecraft.world.item.alchemy.Potions 现在处理 Holder$Reference 而不是超类 Holder
  • net.minecraft.world.item.component
    • AttackRange
      • minRange -> minReach
      • maxRange -> maxReach
      • minCreativeRange -> minCreativeReach
      • maxCreativeRange -> maxCreativeReach
    • BundleContents
      • weight 现在返回一个 DataResult 包装的 Fraction 而不是原始对象
      • getSelectedItem -> getSelectedItemIndex
    • WrittenBookContent
      • tryCraftCopy -> craftCopy
      • resolveForItem, resolve 现在接受 ResolutionContextHolderLookup$Provider 而不是 CommandSourceStackPlayer
  • net.minecraft.world.item.enchantment
    • ConditionalEffect#codec 不再接受 ContextKeySet
    • Enchantment#doLunge -> doPostPiercingAttack
    • EnchantmentHelper#doLungeEffects -> doPostPiercingAttackEffects
    • TargetedConditionalEffect#codec, equipmentDropsCodec 不再接受 ContextKeySet
  • net.minecraft.world.item.enchantment.effects.EnchantmentAttributeEffect#CODEC -> MAP_CODEC
  • net.minecraft.world.item.equipment.Equippable#canBeEquippedBy 现在接受一个持有者包装的 EntityType 而不是原始类型本身
  • net.minecraft.world.item.trading.VillagerTrades#LIBRARIAN_5_EMERALD_NAME_TAGLIBRARIAN_5_EMERALD_YELLOW_CANDLE, LIBRARIAN_5_EMERALD_RED_CANDLE 取代,不是一对一
    • 原始交易已移至 WANDERING_TRADER_EMERALD_NAME_TAG
  • net.minecraft.world.level
    • LevelAccessor 不再实现 LevelReader
    • LevelHeightAccessor#isInsideBuildHeight 现在有一个接受 BlockPos 的重载
  • net.minecraft.world.level.block
    • BigDripleafBlock#canPlaceAt 现在接受 LevelReader 而不是 LevelHeightAccessor,并且不再接受旧状态
    • BubbleColumnBlock#updateColumn 现在接受气泡柱 Block
    • FireBlock#setFlammable 现在是 private 而不是 public
    • MultifaceSpreader$DefaultSpreaderConfig#block 现在是 final
    • SnowyDirtBlock -> SnowyBlock
    • SpreadingSnowyDirtBlock -> SpreadingSnowyBlock
      • 构造函数现在接受 ResourceKey 表示“基础”方块,或当雪或任何其他装饰(例如草)被移除时的方块
  • net.minecraft.world.level.block.entity.TestInstanceBlockEntity
    • getTestBoundingBox - 测试的边界框,按其填充膨胀。
    • getTestBounds - 测试的轴对齐边界框,按其填充膨胀。
  • net.minecraft.world.level.block.entity.vault
    • VaultConfig#DEFAULT, CODEC 现在是 final
    • VaultServerData#CODEC 现在是 final
    • VaultSharedData#CODEC 现在是 final
  • net.minecraft.world.level.block.state
    • BlockBehaviour
      • $BlockStateBase 现在接受一个 PropertyComparable 值的数组,而不是一个值映射,并且不再接受 MapCodec
        • hasPostProcess -> getPostProcessPos,不是一对一
      • $Properties#hasPostProcess -> getPostProcessPos,不是一对一
    • BlockState 现在接受一个 PropertyComparable 值的数组,而不是一个值映射,并且不再接受 MapCodec
    • StateHolder 现在接受一个 PropertyComparable 值的数组,而不是一个值映射,并且不再接受 MapCodec
      • populateNeighbours -> initializeNeighbors,现在是包私有而不是 public;不是一对一
      • getValues 现在返回一个 Property$Value
      • codec 现在接受从某个对象获取状态定义的函数
  • net.minecraft.world.level.chunk.ChunkAccess#blendingData 现在是 final
  • net.minecraft.world.level.chunk.storage.SimpleRegionStorage#upgradeChunkTag 现在接受一个 int 表示目标版本
  • net.minecraft.world.level.gameevent.vibrations.VibrationSystem$Data#CODEC 现在是 final
  • net.minecraft.world.level.gamerules.GameRules 现在有一个接受 GameRule 列表的重载
  • net.minecraft.world.level.levelgen
    • NoiseRouterData#caves 不再接受 NormalNoise$NoiseParametersHolderGetter
    • WorldDimensions#keysInOrder 现在接受一个 LevelStem 键的集合而不是一个流
  • net.minecraft.world.level.levelgen.blockpredicates
    • TrueBlockPredicate#INSTANCE 现在是 final
    • UnobstructedPredicate#INSTANCE 现在是 final
  • net.minecraft.world.level.levelgen.feature
    • AbstractHugeMushrromFeature
      • isValidPosition 现在接受一个 WorldGenLevel 而不是 LevelAccessor
      • placeTrunk 现在接受一个 WorldGenLevel 而不是 LevelAccessor
      • makeCap 现在接受一个 WorldGenLevel 而不是 LevelAccessor
    • BlockBlobFeature 现在使用 BlockBlobConfiguration 泛型
    • Feature
      • FOREST_ROCKBLOCK_BLOB 取代
      • ICE_SPIKESPIKE 取代
    • IceSpikeFeature -> SpikeFeature,不是一对一
      • SpikeFeature 现在是 EndSpikeFeature,不是一对一
        • NUMBER_OF_SPIKES -> EndSpikeFeature#NUMBER_OF_SPIKES
        • getSpikesForLevel -> EndSpikeFeature#getSpikesForLevel
  • net.minecraft.world.level.levelgen.feature.configurations
    • HugeMushroomFeatureConfiguration 现在是一个记录,接受一个可放置的 BlockPredicate
    • SpikeConfiguration -> EndSpikeConfiguration 现在是一个记录
      • 原始的 SpikeConfiguration 现在用于冰刺,接受要使用的方块,以及放置位置的谓词和是否可以替换存在的方块
    • TreeConfiguration
      • dirtProvider, forceDirt 已被 belowTrunkProvider 取代
        • dirtProvider 通常使用 CAN_PLACE_BELOW_OVERWORLD_TRUNKS
        • forceDirt 通常使用 PLACE_BELOW_OVERWORLD_TRUNKS
      • $TreeConfigurationBuilder
        • dirtProvider, dirt, forceDirt 已被 belowTrunkProvider 取代
  • net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacer
    • createFoliage 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
    • placeLeavesRow, placeLeavesRowWithHangingLeavesBelow 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
    • tryPlaceExtension, tryPlaceLeaf 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
  • net.minecraft.world.level.levelgen.feature.rootplacers.RootPlacer#placeRoots, placeRoot 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
  • net.minecraft.world.level.levelgen.feature.stateproviders
    • BlockStateProvider#getState 现在接受 WorldGenLevel
  • net.minecraft.world.level.levelgen.feature.treedecorators
    • TreeDecorator$Context 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
      • level 现在返回 WorldGenLevel 而不是 LevelSimulatedReader
  • net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacer
    • placeTrunk 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
    • setDirtAt -> placeBelowTrunkBlock,现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
    • placeLog 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
    • placeLogIfFree 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
    • validTreePos 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
    • isFree 现在接受一个 WorldGenLevel 而不是 LevelSimulatedReader
  • net.minecraft.world.level.levelgen.placement.BiomeFilter#CODEC 现在是 final
  • net.minecraft.world.level.levelgen.structure.TemplateStructurePiece#template, placeSettings 现在是 final
  • net.minecraft.world.level.levelgen.structure.pools.alias
    • DirectPoolAlias#CODEC 现在是 final
    • RandomGroupPoolAlias#CODEC 现在是 final
    • RandomPoolAlias#CODEC 现在是 final
  • net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings#CODEC 现在是 final
  • net.minecraft.world.level.levelgen.synth.PerlinNoise#getValue 不再接受 boolean 表示是否展平 Y 值而不是应用频率因子
  • net.minecraft.world.level.material.FluidState 现在接受一个 PropertyComparable 值的数组,而不是一个值映射,并且不再接受 MapCodec
  • net.minecraft.world.level.pathfinder.PathType
    • DANGER_POWDER_SNOW -> ON_TOP_OF_POWDER_SNOW
    • DANGER_FIRE -> FIRE_IN_NEIGHBOR
    • DAMAGE_FIRE -> FIRE
    • DANGER_OTHER -> DAMAGING_IN_NEIGHBOR
    • DAMAGE_OTHER -> DAMAGING,
    • DANGER_TRAPDOOR -> ON_TOP_OF_TRAPDOOR
  • net.minecraft.world.level.saveddata.maps.MapItemSavedData#tickCarriedBy 现在接受一个可空的 ItemFrame
  • net.minecraft.world.level.storage.loot.functions
    • EnchantRandomlyFunction 现在接受一个 boolean 表示是否包含来自被附魔堆叠的额外交易成本组件
      • 通过 $Builder#includeAdditionalCostComponent 设置
    • EnchantWithLevelsFunction 现在接受一个 boolean 表示是否包含来自被附魔堆叠的额外交易成本组件
      • 通过 $Builder#includeAdditionalCostComponent 设置
      • $Builder#fromOptions -> withOptions,现在有一个接受可选的 HolderSet 的重载

移除列表

  • net.minecraft.SharedConstants#USE_WORKFLOWS_HOOKS
  • net.minecraft.client.data.models.BlockModelGenerators#createGenericCube
  • net.minecraft.client.Minecraft#delayCrashRaw
  • net.minecraft.client.gui.components.EditBox#setFilter
  • net.minecraft.client.multiplayer.ClientPacketListener#getId
  • net.minecraft.client.renderer.Sheets
    • shieldSheet
    • bedSheet
    • shulkerBoxSheet
    • signSheet
    • hangingSignSheet
    • chestSheet
  • net.minecraft.client.renderer.rendertype.RenderTypes#weather
  • net.minecraft.data.loot.BlockLootSubProvider(Set, FeatureFlagSet, Map, HolderLookup$Provider)
  • net.minecraft.gametest.framework.StructureUtils#DEFAULT_TEST_STRUCTURES_DIR
  • net.minecraft.nbt.NbtUtils
    • addCurrentDataVersion
    • prettyPrint(Tag)
  • net.minecraft.server.packs.AbstractPackResources#getMetadataFromStream
  • net.minecraft.server.players.PlayerList#getSingleplayerData
  • net.minecraft.util
    • Mth#createInsecureUUID
    • LightCoordsUtil#UI_FULL_BRIGHT
  • net.minecraft.world
    • ContainerListener
    • Difficulty#getKey
    • SimpleContainer#addListener, removeListener
  • net.minecraft.world.entity.ai.memory.MemoryModuleType#INTERACTABLE_DOORS
  • net.minecraft.world.entity.monster.Zoglin#MEMORY_TYPES
  • net.minecraft.world.entity.monster.creaking.Creaking#MEMORY_TYPES
  • net.minecraft.world.entity.monster.hogling.Hoglin#MEMORY_TYPES
  • net.minecraft.world.item
    • BundleItem#hasSelectedItem
    • Item#getName()
    • ItemStack
      • isFramed, getFrame
      • setEntityRepresentation, getEntityRepresentation
  • net.minecraft.world.item.component
    • BundleContents
      • getItemUnsafe
      • hasSelectedItem
    • WrittenBookContent#MAX_CRAFTABLE_GENERATION
  • net.minecraft.world.level.block.LiquidBlock#SHAPE_STABLE
  • net.minecraft.world.level.levelgen.feature
    • Feature#isStone, isDirt, isGrassOrDirt
  • net.minecraft.world.level.levelgen.material.WorldGenMaterialRule
  • net.minecraft.world.level.storage.loot.functions.SetOminousBottleAmplifierFunction#amplifier

来源与归属声明

本文档树由以下上游迁移指南汇编而成:

  • 代码库:https://github.com/ChampionAsh5357/neoforged-github
  • 分支:update/26.1
  • 指南根目录:primers/

本次汇编采用的覆盖范围

编译的直接移植指南包含以下上游迁移步骤:

  • 1.21.1 -> 1.21.2/3
  • 1.21.2/3 -> 1.21.4
  • 1.21.4 -> 1.21.5
  • 1.21.5 -> 1.21.6
  • 1.21.6 -> 1.21.7
  • 1.21.7 -> 1.21.8
  • 1.21.8 -> 1.21.9
  • 1.21.9 -> 1.21.10
  • 1.21.10 -> 1.21.11
  • 1.21.11 -> 26.1

归属说明

根据上游primers/README.md声明:

  • 1.12 - 1.15版本迁移指南由@williewillus编写
  • 1.16 - 1.17版本迁移指南由@50ap5ud5编写
  • 所有新版指南(包括本文采用的)均由@ChampionAsh5357编写
  • 文本翻译由@Gugle借助@Deepseek编写

许可证说明

复制到本文档树的详细迁移指南仍遵循其上游许可证及归属要求。

具体许可证文本及上游拆分请查阅:

  • repo/primers/README.md
  • repo/primers/LICENSE-CHAMPIONASH5357
  • repo/primers/LICENSE-50AP5UD5
  • repo/primers/LICENSE-WILLIEWILLUS