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 这一步。
如何使用本网站
如果您知道哪个子系统发生了变化,请使用下面的主题地图。每个链接都直接指向相关章节。
如果同一子系统在多个版本中都发生了变化,请参阅频繁变更的系统了解阅读顺序。
如果您想要原始的入门文档,请参阅详细入门文档,其中包含指向每个章节的锚点链接的完整目录。
如果您遇到编译错误,请使用类和方法的索引来查找它在哪里发生了变化。
主题地图
构建、映射、名称、导入和包移动
- 重命名混乱 (1.21.11)
- ResourceLocation 到 Identifier (1.21.11)
- util 包 (1.21.11)
- critereon 到 criterion (1.21.11)
- 实体和对象子包 (1.21.11)
- Java 25 与反混淆 (26.1)
- JSpecify 注解 (1.21.11)
- 使用注解 (1.21.11)
数据生成、资源包、注册表、标签、编解码器、战利品、验证和配方序列化
- 持有者集过渡 (1.21.2)
- 原料的转变 (1.21.2)
- 配方,现在采用注册表格式 (1.21.2)
- 配方提供者,数据提供者的“并非真正” (1.21.2)
- 乐器,数据包版 (1.21.2)
- 试炼刷怪笼配置,现在采用数据包形式 (1.21.2)
- 条件,通过 HolderGetter 提供 (1.21.2 次要)
- 可编解码的 JSON 重载监听器 (1.21.2 次要)
- 上下文键 (1.21.2 次要)
- SimpleJsonResourceReloadListener (1.21.4 次要)
- MetadataSectionSerializer,被 Codec 取代 (1.21.4 次要)
- 标签与解析 (1.21.5)
- 模型重做 (1.21.5)
- 注册表上下文交换器 (1.21.5 次要)
- 定时器回调,加入编解码器俱乐部! (1.21.5 次要)
- TagAppender 重写 (1.21.6)
- 通用编码与解码:替换直接 NBT 访问 (1.21.6)
- 战利品类型展开 (26.1)
- 验证大修 (26.1)
- 数据包村民交易 (26.1)
- 序列化器记录与配方信息 (26.1)
- 新标签提供者 (26.1 次要)
- 可种植标签 (26.1 次要)
物品、组件、装备、盔甲、工具、战斗、染料和消耗品
- 装备与物品、模型等等 (1.21.2)
- 盔甲材料、装备和模型(纹理) (1.21.2)
- 消耗品 (1.21.2)
- 交互结果 (1.21.2)
- BlockEntityTypes 私有化了! (1.21.2)
- 注册表对象 ID,在属性里? (1.21.2)
- 属性变更 (1.21.2)
- 燃料值 (1.21.2 次要)
- 生物替换当前物品 (1.21.4)
- 武器、工具和盔甲:去除冗余 (1.21.5)
- 数据组件获取器 (1.21.5)
- 组件交互事件 (1.21.5 次要)
- 物品拥有者 (1.21.9 次要)
- 容器使用者 (1.21.9 次要)
- 槽位来源 (1.21.11 次要)
- 新数据组件 (1.21.11)
- 数据组件初始化器 (26.1)
- 物品实例与堆栈模板 (26.1)
- 染料组件 (26.1)
- 数据组件新增 (26.1 次要)
渲染、模型、着色器、粒子、方块模型、物品模型、材质、纹理图集和视觉管线
- GUI 渲染类型 (1.21.2)
- 着色器重写 (1.21.2)
- 实体渲染状态 (1.21.2)
- 雾参数 (1.21.2 次要)
- 发光强度 (1.21.2 次要)
- 地图纹理 (1.21.2 次要)
- 客户端物品 (1.21.4)
- 粒子,通过渲染类型渲染 (1.21.4)
- 渲染管线重做 (1.21.5)
- 模型重做 (1.21.5)
- 纹理图集重做 (1.21.5 次要)
- GUI 变更 (1.21.6)
- Blaze3d 变更 (1.21.6)
- 移除生物效果图集 (1.21.6 次要)
- 动画烘焙 (1.21.6 次要)
- ChunkSectionLayers (1.21.6 次要)
- 小幅迁移 (1.21.7 —— GUI 渲染后续)
- 小幅迁移 (1.21.8 —— GraphicsWorkarounds)
- 功能提交:电影版 (1.21.9)
- 字体字形管线 (1.21.9)
- 客户端资源拆分 (1.21.9 次要)
- 哦,又来了,一次渲染重写 (1.21.11)
- Gizmo 控件 (1.21.11)
- 更多渲染变更 (26.1)
- 实体纹理与成年/幼年模型 (26.1 次要)
- 音频变更 (26.1 次要)
实体、生物、生物 AI、转化、生成和实体数据
- 交互结果 (1.21.2)
- 爆——炸——! (1.21.2 次要 ——
Explosion现在是一个接口) - 生物转化 (1.21.2 次要 ——
Mob#convertTo已变更) - 矿车行为 (1.21.2 次要)
- 末影珍珠加载区块 (1.21.2 次要)
- 实体引用 (1.21.5 次要 —— UUID 被
EntityReference取代) - 拴绳 (1.21.6 次要)
- 类型化实体数据 (1.21.9 次要)
- 名称和 ID (1.21.9 次要)
- interactAt 的移除 (26.1 次要 ——
Entity#interactAt已移除) - 活动与大脑 (26.1 次要 —— AI 大脑系统变更)
- 更多实体声音变种注册表 (26.1 次要)
- 僵尸鹦鹉螺变体 (1.21.11 次要)
GUI、输入、按键绑定、调试屏幕、调试工具、RPC 工具和测试基础设施
- GUI 渲染类型 (1.21.2)
- 游戏测试大修 (1.21.5)
- GUI 变更 (1.21.6)
- 小幅迁移 (1.21.7)
- 调试大修 (1.21.9)
- 调试屏幕 (1.21.9)
- JSON-RPC 管理服务器 (1.21.9)
- 输入处理整合 (1.21.9)
- 光标类型 (1.21.9 次要)
- Gizmo 控件 (1.21.11)
- 文本收集器 (1.21.11 次要)
- OptionEnum 移除 (1.21.11 次要)
- 容器屏幕变更 (26.1 次要)
- 输入消息编辑器支持 (26.1 次要)
- 测试环境状态追踪 (26.1 次要)
世界状态、保存数据、游戏规则、时间线、时钟、玩家、权限、路径点和其他服务端系统
- 正确处理方块实体的移除 (1.21.5)
- 体素形状辅助类 (1.21.5)
- 加权列表重做 (1.21.5)
- 加载票 (1.21.5)
- 保存数据,现在带有类型 (1.21.5)
- 方块效果应用器 (1.21.5 次要)
- 路径点 (1.21.6)
- 服务端玩家变更 (1.21.6)
- 权限来源 (1.21.6 次要)
- Level#isClientSide 现在为 private (1.21.9)
- 加载票标志 (1.21.9 次要)
- 重生数据 (1.21.9 次要)
- 权限大修 (1.21.11)
- 环境属性的时间线 (1.21.11)
- 游戏规则洗牌 (1.21.11)
- Level#random 字段现在为 protected (26.1)
- 世界时钟与时间标记 (26.1)
- 将主关卡数据拆分为保存数据 (26.1)
- 聊天权限 (26.1 次要)
- ChunkPos,现在是一个记录 (26.1 次要)
- 炼药锅交互调度器 (26.1 次要)
- 流体逻辑重组 (26.1 次要)
- 移除随机斑块特征 (26.1 次要)
- 基于规则的方块状态提供者 (26.1 次要)
- 文件修缮工 (26.1 次要)
其余的小幅迁移
- 语言文件的移除与重命名 (1.21.2)
- MacosUtil#IS_MACOS (1.21.2)
- 更智能的帧率限制 (1.21.2)
- 朝向 (1.21.2)
- 移除雕刻生成步骤 (1.21.2)
- 连续执行器 (1.21.2)
- 分析器与 Tracy 客户端 (1.21.2)
- Tick节流器 (1.21.2)
- 音乐,现在带有音量控制 (1.21.4)
- 解作用域玩家参数 (1.21.5)
- 重载实例创建 (1.21.5)
- JOML 后端接口 (1.21.5)
- 状态效果字段重命名 (1.21.5)
- 重载监听器共享状态 (1.21.9)
- “在架子上” 变换 (1.21.9)
- 共享文本区域调试器 (1.21.11)
- 特定逻辑变更 (1.21.11)
- 类型化实例 (26.1)
- 不再有绊线管线 (26.1)
- 环境属性新增 (26.1)
- 特定逻辑变更 (26.1)
每份入门文档的“小幅迁移”章节中还包含“新标签”、“标签变更”、“新增列表”、“变更列表”和“移除列表”子章节。如需查看这些内容,请前往详细入门文档中的完整入门文档页面。
类和方法索引
如果您遇到编译错误或需要查找特定类/方法在哪里发生了变化,请在此表中搜索。
| 类 / 方法 | 版本 | 章节 |
|---|---|---|
AbstractFurnaceBlockEntity 燃料 | 1.21.2 | 燃料值 |
AbstractMinecart | 1.21.2 | 矿车行为 |
Activities / Brain | 26.1 | 活动与大脑 |
AnimationDefinition#bake | 1.21.6 | 动画烘焙 |
ArmorItem / ArmorMaterial | 1.21.2 | 盔甲材料、装备和模型(纹理) |
BakedModel / BakedQuad | 1.21.5 | 模型重做 |
BlockBehaviour#neighborChanged | 1.21.2 | 朝向 |
BlockEntityType 构造器 | 1.21.2 | BlockEntityTypes 私有化了! |
CauldronInteraction | 26.1 | 炼药锅交互调度器 |
ChunkPos (现为记录) | 26.1 | ChunkPos,现在是一个记录 |
ChunkSectionLayer | 1.21.6 | ChunkSectionLayers |
| 客户端物品 JSON | 1.21.4 | 客户端物品 |
Consumable / ConsumableListener | 1.21.2 | 消耗品 |
DataComponents 获取器 | 1.21.5 | 数据组件获取器 |
DataComponents 新类型 | 1.21.11 | 新数据组件 |
DataComponents 初始化器 | 26.1 | 数据组件初始化器 |
DiggerItem / SwordItem 移除 | 1.21.5 | 武器、工具和盔甲:去除冗余 |
DyeRecipe / DyeItem | 26.1 | 染料组件 |
Entity#interactAt 移除 | 26.1 | interactAt 的移除 |
EntityReference (取代 UUID) | 1.21.5 | 实体引用 |
EntityRenderState | 1.21.2 | 实体渲染状态 |
Explosion (现为接口) | 1.21.2 | 爆——炸——! |
GameRules | 1.21.11 | 游戏规则洗牌 |
GameTest 框架 | 1.21.5 | 游戏测试大修 |
GenerationStep$Carving 移除 | 1.21.2 | 移除雕刻生成步骤 |
GpuTexture / RenderPipeline | 1.21.5 | 渲染管线重做 |
GuiGraphics / GUI 渲染 | 1.21.6 | GUI 变更 |
Holder / HolderSet / HolderGetter | 1.21.2 | 持有者集过渡 |
Identifier (原 ResourceLocation) | 1.21.11 | ResourceLocation 到 Identifier |
Ingredient | 1.21.2 | 原料的转变 |
InteractionResult | 1.21.2 | 交互结果 |
ItemInstance / StackTemplate | 26.1 | 物品实例与堆栈模板 |
KeyMapping / 输入事件 | 1.21.9 | 输入处理整合 |
Leashable | 1.21.6 | 拴绳 |
Level#isClientSide | 1.21.9 | Level#isClientSide 现在为 private |
Level#random | 26.1 | Level#random 字段现在为 protected |
LootContextParam / LootContextParamSet | 1.21.2 | 上下文键 |
LootPoolEntry / 战利品编解码器 | 26.1 | 战利品类型展开 |
Mob#convertTo | 1.21.2 | 生物转化 |
OptionEnum 移除 | 1.21.11 | OptionEnum 移除 |
Permission / PermissionSet | 1.21.11 | 权限大修 |
Profiler#get (取代 getProfiler) | 1.21.2 | 分析器与 Tracy 客户端 |
Recipe 注册表格式 | 1.21.2 | 配方,现在采用注册表格式 |
RecipeDisplay / SlotDisplay | 1.21.2 | 配方,现在采用注册表格式 |
RenderType 洗牌 | 1.21.11 | 哦,又来了,一次渲染重写 |
SavedData / SavedDataType | 1.21.5 | 保存数据,现在带有类型 |
ServerExplosion | 1.21.2 | 爆——炸——! |
着色器 JSON / .vsh / .fsh | 1.21.2 | 着色器重写 |
SimpleJsonResourceReloadListener | 1.21.4 | SimpleJsonResourceReloadListener |
TagProvider 追加器 | 1.21.6 | 标签提供者:追加器重写 |
Validatable / ValidationContext | 26.1 | 验证大修 |
| 村民交易(数据包) | 26.1 | 数据包村民交易 |
VoxelShape 辅助类 | 1.21.5 | 体素形状辅助类 |
Waypoint 系统 | 1.21.6 | 路径点 |
| 世界时钟 / 时间标记 | 26.1 | 世界时钟与时间标记 |
| 世界数据拆分 | 26.1 | 将主关卡数据拆分为保存数据 |
来源与署名
拆分后的入门文档页面复制自 ChampionAsh5357/neoforged-github,分支 update/26.1。详见来源与署名。
频繁变更的系统
此页面是直接移植的防护栏。
当同一子系统在多个中间版本中发生变化时,不要将最早的迁移说明视为最终版本。请使用最新的适用版本作为真实来源,但仍需先应用旧章节的内容,这样才能使中间的 API 过渡看起来合理。
渲染与图形
相关章节:
- GUI 渲染类型 (1.21.2)
- 着色器重写 (1.21.2)
- 实体渲染状态 (1.21.2)
- 渲染管线重做 (1.21.5)
- 模型重做 (1.21.5)
- GUI 变更 (1.21.6)
- Blaze3d 变更 (1.21.6)
- 小幅迁移 (1.21.7)
- 功能提交:电影版 (1.21.9)
- 字体 字形 管线 (1.21.9)
- 哦,又来了,一次渲染重写 (1.21.11)
- 更多渲染变更 (26.1)
如何阅读它们:
1.21.2/3修改了 GUI 贴图混合、着色器 JSON 结构以及渲染状态假设。1.21.5是第一次大型渲染基础设施重写,围绕RenderPipeline、GpuTexture和渲染通道展开。1.21.6通过准备/渲染状态分离再次修改了 GUI 渲染流程。1.21.9修改了功能提交到渲染的方式。1.21.11修改了采样器、渲染类型、地形拆分和纹理图集。26.1是方块/物品渲染、材质、染色源、流体模型、粒子层以及面向后端的渲染 API 的最终权威。
实用规则:
- 将
26.1视为最终的渲染目标。 - 保留
1.21.4客户端物品和1.21.6GUI 流程作为仍然有效的要求,而不是过时的历史。
物品模型与物品元数据
相关章节:
- 客户端物品 (1.21.4)
- 生物替换当前物品 (1.21.4)
- 粒子,通过渲染类型渲染 (1.21.4)
- 武器、工具和盔甲:去除冗余 (1.21.5)
- 数据组件获取器 (1.21.5)
- 功能提交:电影版 (1.21.9)
- 哦,又来了,一次渲染重写 (1.21.11)
- 新数据组件 (1.21.11)
- 数据组件初始化器 (26.1)
- 物品实例与堆栈模板 (26.1)
- 染料组件 (26.1)
- 更多渲染变更 (26.1)
哪些内容留存下来:
1.21.4客户端物品是物品渲染数据的基线。1.21.5移除了更多硬编码的物品类假设,改用组件和装备数据。1.21.9、1.21.11和26.1进一步改变了物品参与渲染和元数据管道的方式。
实用规则:
- 首先将物品资源转换为客户端物品。
- 然后围绕组件移植行为和元数据。
- 最后对照
26.1的渲染和物品实例模型进行验证。
标签、注册表、编解码器与验证
相关章节:
- 持有者集过渡 (1.21.2)
- 注册表对象 ID,在属性里? (1.21.2)
- 配方,现在采用注册表格式 (1.21.2)
- 标签与解析 (1.21.5)
- TagAppender 重写 (1.21.6)
- 通用编码与解码:替换直接 NBT 访问 (1.21.6)
- 重命名混乱 (1.21.11)
- 战利品类型展开 (26.1)
- 验证大修 (26.1)
- 序列化器记录与配方信息 (26.1)
哪些内容留存下来:
1.21.2/3是Holder和HolderSet开始影响代码库大部分内容的版本。1.21.5修改了标签访问、解析器行为、基于编解码器的读写以及保存数据的构造。1.21.6修改了标签提供者的构建方式,并推动更多代码转向通用编码和解码。1.21.11带来了重命名的变动,影响注册表和标识符相关的代码。26.1通过战利品类型展开和验证大修最终确定了更多基于编解码器的基础设施。
实用规则:
- 前面的章节告诉您如何迁移到基于持有者和编解码器的 API。
26.1是验证和战利品注册形式的最终目标。
数据组件
相关章节:
- 消耗品 (1.21.2)
- 装备与物品、模型等等 (1.21.2)
- 原料的转变 (1.21.2)
- 配方,现在采用注册表格式 (1.21.2)
- 武器、工具和盔甲:去除冗余 (1.21.5)
- 数据组件获取器 (1.21.5)
- 新数据组件 (1.21.11)
- 数据组件初始化器 (26.1)
- 染料组件 (26.1)
哪些内容留存下来:
1.21.2/3引入了重要的组件相关迁移,例如消耗品和配方相关数据的移动。1.21.5扩展了以组件为中心的工具、盔甲、武器以及通用数据访问行为。1.21.11添加了更多组件类型。26.1继续添加初始化器、染料组件以及更多组件。
实用规则:
- 随着版本推进,物品和配方将越来越少地由类驱动,而越来越多地由组件驱动。
保存数据与世界状态
相关章节:
- 保存数据,现在带有类型 (1.21.5)
- 将主关卡数据拆分为保存数据 (26.1)
- 世界时钟与时间标记 (26.1)
哪些内容留存下来:
1.21.5将保存数据迁移到SavedDataType。26.1进一步将主关卡数据拆分到专用的保存数据对象中。
实用规则:
- 先完成
1.21.5的迁移,然后在26.1中重新审视每个关卡/世界持久化的假设。
开发者工具、测试、调试与权限
相关章节:
- 游戏测试大修 (1.21.5)
- 调试大修 (1.21.9)
- 调试屏幕 (1.21.9)
- JSON-RPC 管理服务器 (1.21.9)
- 权限大修 (1.21.11)
- Gizmo 控件 (1.21.11)
- Java 25 与反混淆 (26.1)
哪些内容留存下来:
1.21.5大修了游戏测试。1.21.9大修了调试和管理服务器的形态。1.21.11添加了权限大修和以 gizmo 为中心的可视化工作。26.1添加了 Java 25 以及更多面向工具的小改动。
实用规则:
- 先移植游戏玩法代码。
- 然后根据后续章节重新启用您的调试、测试和仅限操作员的工具。
详细入门文档
这些章节按步骤保留了上游入门文档的内容。每个章节标题都直接链接到入门文档页面内的相应章节。
1.21.1 -> 1.21.2/3
- 资源包变更
- 持有者集过渡
- GUI 渲染类型
- 着色器重写
- 实体渲染状态
- 装备与物品、模型等等
- 盔甲材料、装备和模型(纹理)
- 交互结果
- 乐器,数据包版
- 试炼刷怪笼配置,现在采用数据包形式
- 配方提供者,数据提供者的“并非真正”
- 原料的转变
- BlockEntityTypes 私有化了!
- 消耗品
- 注册表对象 ID,在属性里?
- 属性变更
- 配方,现在采用注册表格式
- 小幅迁移
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
- 资源包变更
- Java 25 与反混淆
- 战利品类型展开
- 验证大修
- 数据包村民交易
Level#random字段现在为 protected- 数据组件初始化器
- 物品实例与堆栈模板
- 序列化器记录与配方信息
- 染料组件
- 世界时钟与时间标记
- 将主关卡数据拆分为保存数据
- 更多渲染变更
- 小幅迁移
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"
}
通常,除了在提供者生成期间,您永远不应该在代码中构造持有者集。每种集类型都有不同的构造方法。
首先,要处理 Holder 或 HolderSet,您需要通过 Registry 访问静态注册表实例,或者通过 HolderGetter 访问数据包注册表。HolderGetter 可以在数据包注册表生成期间从 BootstrapContext#lookup 获得,或者在生成期间或游戏过程中的 MinecraftServer#registryAccess 从 HolderLookup$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)->blitAndBlendToScreennet.minecraft.client.gui.GuiGraphicsdrawManaged已移除setColor已移除 - 现在是blit和blitSprite方法中的一个参数blit(int, int, int, int, int, TextureAtlasSprite, *)已移除bufferSource->drawSpecial,不是一对一,因为该方法接受一个MultiBufferSource的消费者,并结束当前批次,而不是仅仅返回MultiBufferSource
net.minecraft.client.gui.components.PlayerFaceRenderer- 除
draw(GuiGraphics, PlayerSkin, int, int, int)之外的所有draw方法都接受一个额外的int参数,用于定义颜色
- 除
net.minecraft.client.renderer.RenderType-guiTexturedOverlay- 获取叠加在游戏屏幕上的图像的渲染类型。 -guiOpaqueTexturedBackground- 获取应用于菜单背景的 GUI 纹理的渲染类型。 -guiNauseaOverlay- 获取恶心覆盖层的渲染类型。 -guiTextured- 获取 GUI 菜单内图像的渲染类型。net.minecraft.client.resources.metadata.gui.GuiSpriteScaling$NineSlice现在接受一个布尔值,表示纹理的中心部分是否应拉伸以适应大小。
着色器重写
着色器的内部实现已被大量重写。
着色器文件
主要变更是定义的采样器和后期着色器。
DiffuseSampler 和 DiffuseDepthSampler 已根据应用目标被赋予新名称:InSampler、MainSampler 和 MainDepthSampler。InSampler 用于除 transparency 程序着色器之外的所有场景。
// 在某个着色器 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() {
// 在此处设置输出值
}
在代码方面,着色器在内部存储为 ShaderProgram 或 CompiledShaderProgram。ShaderProgram 表示标识符,而 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.buffersBufferType- 一个枚举,指定 GL 目标缓冲区类型。GpuBuffer- 围绕 GL 缓冲区调用的包装器,用于处理屏幕渲染。GpuFence- 用于管理 GPU 围栏同步状态的句柄。
com.mojang.blaze3d.platform.GlStateManagerglShaderSource现在接受一个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.shadersBlendMode、Effect、EffectProgram、Program、ProgramManager、Shader已被整合到CompiledShader中Unform不再接受ShaderglGetAttribLocation已移除glBindAttribLocation->VertexFormat#bindAttributessetFromConfig- 根据另一个统一配置的值和计数设置统一参数。
com.mojang.blaze3d.systems.RenderSystemsetShader现在接受CompiledShaderProgram或ShaderProgramclearShader- 清除当前系统着色器。runAsFancy已移除,由LevelRenderer#getTransparencyChain内部处理setProjectionMatrix现在接受一个ProjectionType而不仅仅是VertexSortinggetVertexSorting->getProjectionType;不是一对一,但VertexSorting可在ProjectionType上访问
com.mojang.blaze3d.vertex.VertexBufferdrawWithShader在传入null的CompiledShaderProgram时将成为空操作$Usage->com.mojang.blaze3d.buffers.BufferUsage
net.minecraft.client.Minecraft#getShaderManager- 返回管理所有着色器和后处理效果的管理器。net.minecract.client.rendererEffectInstance类已移除,在大多数情况下被CompiledShaderProgram取代GameRendererget*Shader->CoreShaders#*shutdownEffect->clearPostEffectcreateReloadListener->ShaderManagercurrentEffect->currentPostEffect
ItemBlockRenderTypes#getRenderType不再接受一个表示是否使用半透明渲染类型的布尔值ShaderInstance->CompiledShaderProgramCHUNK_OFFSET->MODEL_OFFSET- JSON 着色器:
ChunkOffset->ModelOffset
- JSON 着色器:
getUniformConfig- 返回给定名称的统一变量的配置。
LevelRenderer#graphicsChanged已移除,由LevelRenderer#getTransparencyChain内部处理PostChainConfig- 表示后处理效果着色器 JSON 如何构建的配置。PostPass现在接受代表输出目标的ResourceLocation而不是输入和输出RenderTarget或boolean过滤模式,要使用的CompiledShaderProgram而不是ResourceProvider,以及着色器要使用的一组统一变量- 不再实现
AutoCloseable addToFrame不再接受float时间getEffect->getShaderaddAuxAsset->addInputprocess->addToFrame$Input- 表示后处理效果着色器的输入。$TargetInput- 来自RenderTarget的输入。$TextureInput- 来自纹理的输入。
- 不再实现
PostChain构造函数现在通过load创建- 不再实现
AutoCloseable MAIN_RENDER_TARGET现在是公开的getName已移除,被ShaderProgram#configId取代process不再接受DeltaTracker$TargetBundle- 处理链中资源句柄的获取和替换。
- 不再实现
RenderTypeentityTranslucentCull、entityGlintDirect已移除armorTranslucent- 一种渲染类型,用于渲染可以具有半透明纹理的盔甲。
ShaderDefines- 着色器用作常量的定义值和标志。ShaderManager- 加载着色器的资源监听器。ShaderProgram- 着色器的标识符。ShaderProgramConfig- 程序着色器 JSON 的定义。Sheets#translucentCullBlockSheet已移除SkyRenderer现在实现AutoCloseable
net.minecraft.client.renderer.entity.ItemRenderergetFoilBufferDirect已移除,被getFoilBuffer取代ITEM_COUNT_BLIT_OFFSET->ITEM_DECORATION_BLIT_OFFSET
实体渲染状态
由于 EntityRenderState 的加入,实体模型和渲染器几乎完全重做。EntityRenderState 本质上是数据对象类,只公开渲染实体所需的计算信息。例如,Llama 不需要知道它的背包里有什么,只需要知道它有一个箱子要在层中渲染。
首先,您需要选择要使用的 EntityRenderState,或者如果需要将额外信息传递给渲染器,则使用子类创建一个。最常见的子类状态是 EntityRenderState 或用于活体的 LivingEntityRenderState。这些字段应该是可变的,因为状态类只为每个渲染器创建一次。
// 假设 MyEntity 继承 LivingEntity
public class MyEntityRenderState extends LivingEntityRenderState {
// 字段示例
boolean hasExampleData;
}
然后,您创建将渲染实体的 EntityModel。EntityModel 有一个泛型,接受 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,获取根 ModelPart;allParts,返回所有 ModelPart 的扁平列表;以及 resetPose,将 ModelPart 恢复到其默认状态。
LayerDefinition、MeshDefinition、PartDefinition 和 CubeDeformation 在 LayerDefinitions 中 ModelLayerLocation -> LayerDefinition 映射的实现和构造保持不变。
模型变换呢?例如,实体的幼年版本,或者模型完全切换的情况?在这些情况下,为每个模型注册一个单独的层定义。例如,Llama 将有一个用于主 Llama 模型的模型层、幼年模型层、成年和幼年装饰层,以及最后用于唾沫的层。由于模型通常彼此相似,只有轻微的变换,LayerDefinition 添加了一个新方法来接受 MeshTransformer。MeshTransformer 基本上是 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,不过这次它接受渲染状态而不是实体。需要实现/覆盖的新方法是 createRenderState 和 extractRenderState。createRenderState 构造默认渲染状态对象。而 extractRenderState 则填充当前正在渲染的实体的渲染状态。如果您没有使用现有的渲染状态类,则需要覆盖 extractRenderState。
当然,还有 EntityRenderer 的子类。首先,有 LivingEntityRenderer。它有一个额外的泛型,即正在渲染的 EntityModel,并在构造函数中接受该值以及阴影半径。这个渲染器还接受 RenderLayer,如果您通过渲染状态访问之前的参数,这些层基本保持不变。然后是 MobRenderer,所有实体都扩展它。最后是 AgeableMobRenderer,它接受两个模型——成年和幼年——并根据 LivingEntityRenderState#isBaby 决定渲染哪个。如果实体有幼年形态,应该使用 AgeableMobRenderer 配合 BabyModelTransform。否则,您很可能使用 MobRenderer 或 EntityRenderer。
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.modelAbstractBoatModel- 一个模型,假设存在left_paddle和right_paddle,并根据船的划桨时间进行动画。AgeableHierarchicalModel、ColorableAgeableListModel、AgeableListModel->BabyModelTransformAnimationUtilsanimateCrossbowCharge现在接受一个表示充能持续时间的float和一个表示使用刻数的int,而不是LivingEntityswingWeaponDown现在接受一个HumanoidArm而不是Mob
BabyModelTransform- 一种网格变换器,应用模型的幼年缩放形式。BoatModelcreatePartsBuilder已移除createChildren->addCommonParts,现在是私有的createBodyModel->createBoatModel、createChestBoatModelwaterPatch->createWaterPatchparts已移除
ChestBoatModel->BoatModel#createChestBoatModelChestedHorseModel类已移除,现在完全存在于LlamaModel和DonkeyModel中ChestRaftModel->RaftModel#createChestRaftModelColorableHierarchicalModel现在存储在单独的EntityRenderState中EntityModel- 泛型现在接受
EntityRenderState setupAnim只接受EntityRenderState泛型prepareMobModel已移除copyPropertiesTo已移除,仍然存在于HumanoidModel中
- 泛型现在接受
HierarchicalModel类已移除HumanoidModel#rotLerpRad->Mth#rotLerpRadListModel类已移除ModelrenderToBuffer现在是 final 的root- 返回根ModelPart。getAnyDescendantWithName- 返回根中具有指定名称的第一个后代。animate- 给定动画的当前状态和定义,在当前时间和最大时间之间变换模型以播放动画。animateWalk- 对模型的行走循环进行动画。applyStatic- 将即时动画应用于指定状态。$Simple- 构造一个没有额外动画的简单模型。
ModelUtils类已移除ParrotModel#getState->getPose,现在是公开的PlayerModel不再有泛型renderEars->PlayerEarsModelrenderCape->PlayerCapeModelgetRandomModelPart->getRandomBodyPartgetArmPose- 返回玩家给定其渲染状态的手臂姿势。
RaftModel#createBodyModel->createRaftModelWardenModel#getTendrilsLayerModelParts、getHeartLayerModelParts、getBioluminescentLayerModelParts、getPulsatingSpotsLayerModelParts现在接受WardenRenderStateWaterPatchModel->BoatModel#createWaterPatch和Model$Simple
net.minecraft.client.model.geomModelLayerLocation现在是一个记录ModelLayerscreateRaftModelName、createChestRaftModelName已移除createSignModelName->createStandingSignModelName、createWallSignModelNamecreateBoatModelName、createChestBoatModelName已移除
ModelPartrotateBy- 使用给定的Quaternionf旋转部件。$Cube#polygons、$Polygon、$Vertex现在是公开的
PartPose现在是一个记录translated- 平移一个姿势。withScale、scaled- 缩放一个姿势。
net.minecraft.client.model.geom.buildersLayerDefinition#apply- 对定义应用网格变换器并返回一个新的。MeshDefinition#transformed- 对根姿势应用变换并返回一个新的。MeshTransformer- 将现有的MeshDefinition转换为给定形式。PartDefinitionaddOrReplaceChild现在有一个接受PartDefinition的重载clearChild- 从部件定义中移除子部件。getChildren- 获取当前部件的所有子部件。transformed- 对当前姿势应用变换并返回一个新的。
net.minecraft.client.renderer.entityAbstractBoatRenderer- 一个船渲染器,包含用于船模型和船本身任何附加内容的方法。AgeableMobRenderer- 一个接受幼年和成年模型的生物渲染器。BoatRenderer现在接受一个ModelLayerLocation而不是booleanEntityRenderDispatcher现在接受一个MapRendererrender不再接受实体的 Y 旋转
EntityRenderer现在接受EntityRenderState的泛型getRenderOffset只接受EntityRenderStategetBoundingBoxForCulling- 返回实体的边界框以确定是否剔除。affectedByCulling- 返回实体是否可以被剔除。render只接受渲染状态,以及堆栈、缓冲区源和包光shouldShowName现在接受一个double表示相机到实体的平方距离getTextureLocation已移除,被移动到使用它的类中,如LivingEntityRenderer- 后续的
getTextureLocation实现可能是 protected 或 private
- 后续的
renderNameTag现在接受渲染状态而不是实体,并移除了部分刻floatgetNameTag- 从实体获取名称标签。getShadowRadius现在接受渲染状态而不是实体createRenderState- 创建渲染状态对象。extractRenderState- 将实体中的任何数据读取到渲染状态。
EntityRendererProvider$Context接受MapRenderer而不是ItemInHandRendererLivingRendererisShaking现在接受渲染状态而不是实体setupRotations现在接受渲染状态而不是实体getAttackAnim、getBob现在在渲染状态中getFlipDegrees不再接受实体getWhiteOverlayProgress现在接受渲染状态而不是实体,并且不再接受实体的 Y 旋转scale现在接受渲染状态而不是实体,并且不再接受实体的 Y 旋转shouldShowName现在接受一个double表示到相机的平方距离getShadowRadius现在接受渲染状态而不是实体
RaftRenderer- 一个实现AbstractBoatRenderer的木筏渲染器。RenderLayerParent#getTextureLocation已移除
net.minecraft.client.renderer.entity.layersEnergySwirlLayer#isPowered- 返回能量是否被充能。CustomHeadLayer和#translateToHead接受一个CustomHeadLayer$Transforms而不是硬编码变换的缩放信息PlayerItemInHandRenderer接受一个ItemRenderer而不是ItemInHandRendererRenderLayer接受EntityRenderState泛型而不是Entity泛型coloredCutoutModelCopyLayerRender接受一个EntityModel,状态信息捆绑在渲染状态中renderColoredCutoutModel接受非泛型形式的渲染信息,假设为LivingEntityRenderStategetTextureLocation已移除,改为直接传递到适当的位置render现在接受渲染状态而不是实体和参数信息
SaddleLayer有一个接受幼年模型的构造函数。SheepFurLayer->SheepWoolLayerStuckInBodyLayer现在接受要应用卡住对象的模型、卡住对象的纹理以及对象的放置样式numStuck现在接受渲染状态而不是实体renderStuckItem现在是私有的
WardenEmissiveLayer->LivingEntityEmissiveLayer,一个更通用的实现
net.minecraft.client.renderer.entity.player.PlayerRendererrenderRightHand、renderLeftHand现在接受一个ResourceLocation而不是AbstractClientPlayer,以及一个boolean表示是否渲染左袖和/或右袖setupRotations现在接受渲染状态而不是实体和参数信息
net.minecraft.world.entityAnimationState#copyFrom- 从另一个状态复制动画状态。EntitynoCulling->EntityRenderer#affectedByCullinggetBoundingBoxForCulling->EntityRenderer#getBoundingBoxForCulling
LerpingModel类已移除PowerableMob类已移除
模型烘焙
UnbakedModel 现在有一个不同的方法来解析任何依赖项。不再获取依赖项并解析父级,而是通过一个称为 resolveDependencies 的单一方法完成。该方法接受 Resolver。Resolver 负责获取 ResourceLocation 的 UnbakedModel。
// 对于某个 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.blockBlockModel#getDependencies、resolveParents->resolveDependenciesBlockModelDefintion现在接受一个MultiPart$Definition,不存在接受List<BlockModelDefinition>的构造函数fromStream、fromJsonElement不再接受$ContextgetVariants已移除isMultiPart已移除instantiate->MultiPart$Definition#instantiate
MultiVariant现在是一个记录UnbakedBlockStateModel- 一个表示方块状态模型的接口,包含一个将具有相同模型的状态分组在一起的单一方法。VariantSelector- 用于从模型描述符构建状态定义的工具。
net.minecraft.client.renderer.block.modelBlockModelMISSING_MATERIAL- 缺失方块纹理的材质。bake不再接受ModelBaker和BlockModel$LoopException类已移除
net.minecraft.client.renderer.block.model.multipart.MultiPart现在实现UnbakedBlockStateModelgetSelectors->$Definition#selectorsgetMultiVariants->$Definition#getMultiVariants
net.minecraft.client.resources.modelBakedModel#getOverrides->overrides,方法默认为空覆盖BlockStateModelLoader只接受缺失的未烘焙模型loadAllBlockStates已移除definitionLocationToBlockMapper- 从给定的资源位置获取状态定义loadBlockStateDefinitions->loadBlockStateDefinitionStackgetModelGroups->ModelGroupCollector$LoadedJson->$LoadedBlockModelDefinition$LoadedModel现在是公开的$LoadedModels- 一个将模型位置映射到已加载模型的记录。
BuiltInModel不再接受ItemOverridesDelegateBakedModel- 一个将所有逻辑委托给提供的BakedModel的工具实现Material#buffer接受另一个boolean,用于处理是否应用闪光效果MissingBlockModel- 方块的缺失模型。ModelBaker#getModel已移除,ModelBakery$ModelBakerImpl中的实现是私有的ModelBakery只接受顶层模型、所有未烘焙模型和缺失模型BUILTIN_SLASH->SpecialModels#builtinModelIdBUILTIN_SLASH_GENERATED->SpecialModels#BUILTIN_GENERATEDBUILTIN_BLOCK_ENTITY->SpecialModels#BUILTIN_BLOCK_ENTITYMISSING_MODEL_LOCATION->MissingBlockModel#LOCATIONMISSING_MODEL_VARIANT->MissingBlockModel#VARIANTGENERATION_MARKER->SpecialModels#GENERATED_MARKERBLOCK_ENTITY_MARKER->SpecialModels#BLOCK_ENTITY_MARKERgetModelGroups->ModelGroupCollector
ModelDiscovery- 方块和物品模型的加载器,例如在读取时如何解析它们。ModelGroupCollector- 一个方块状态收集器,用于将状态映射到它们关联的方块模型。ModelResourceLocation#vanilla已移除MultiPartBakedModel字段现在从选择器中的第一个模型获取,并且是私有的$Builder类已移除,被$Selector取代
SimpleBakedModel、SimpleBakedModel$Builder不再接受ItemOverridesSpecialModels- 内置模型的工具。UnbakedModelgetDependencies、resolveParents->resolveDependenciesbake不再可为 null$Resolver- 确定在顶层或覆盖时如何加载未烘焙模型。
WeightedBakedModel现在接受一个SimpleWeightedRandomList而不是WeightedEntry的列表
装备与物品、模型等等
装备和物品经历了重大改革,其中大部分分散在整个文档中。这是一些核心变更,虽然它们很重要,但由于易于更改,不值得详细解释。
物品名称和模型
物品名称和模型现在直接通过属性中的 ITEM_NAME 和 ITEM_MODEL 数据组件设置。默认情况下,这将使用与以前相同的名称和模型位置,但可以通过 Item$Properties#overrideDescription 和 #overrideModel 设置。overrideDescription 接受要使用的翻译键。还有 useBlockDescriptionPrefix 和 useItemDescriptionPrefix 分别将其更改为默认的方块和物品翻译键。overrideModel 接受模型 JSON 的相对 ResourceLocation。例如,值 examplemod:example_item 将映射到 examplemod:example_item#inventory 的 ModelResourceLocation。这旨在链接到 assets/examplemod/models/item/example_item.json 的模型 JSON。
物品模型有一个小特性。如果模组制作者决定在
inventory变体下在该位置加载特殊模型,则相同的键也可以指向assets/examplemod/models/example_item.json。因此,建议避免在根models和models/item子目录中使用同名模型名称。
可附魔、可修复物品
附魔值和修复物品检查正在被数据组件取代:分别是 DataComponents#ENCHANTABLE 和 DataComponents#REPAIRABLE。这些可以通过 Item$Properties#enchantable 和 #repairable 设置。因此,Item#getEnchantmentValue 和 isValidRepairItem 已移除。
鞘翅 -> 滑翔翼
任何物品如果装备了 DataComponents#GLIDER 值,都可以像鞘翅一样行动。这基本上作为一个标志,表示该物品可用于滑翔。这仅在该物品也有 DataComponents#EQUIPPABLE 条目时有效。
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 并只允许特定实体穿戴它们。
这是否意味着 ArmorItem 和 AnimalArmorItem 实际上毫无意义?对于 AnimalArmorItem,这可以争论。AnimalArmorItem 所做的只是有一个 $BodyType 参数,这意味着盔甲只能应用于马或狼,并指定物品破碎声音。另一方面,ArmorItem 只有一个特定用例:确定物品是否可以脱下或交换。这隐式检查当前穿戴的盔甲物品,看它是否不能脱下(通过 PREVENT_ARMOR_CHANGE 附魔),并计算替换盔甲材料上的属性,以便任何热交换只会提高穿戴者的盔甲属性值。
让我们深入一层。
数据组件
ArmorMaterial 指定了要应用于物品的八个数据组件:
MAX_DAMAGE- 设置为物品的最大耐久度乘以ArmorType单位耐久度MAX_STACK_SIZE- 设置为 1DAMAGE- 设置为 0ATTRIBUTE_MODIFIERS- 设置ARMOR和ARMOR_TOUGHNESS属性,以及当大于 0 时的KNOCKBACK_RESISTANCEENCHANTABLE- 设置为附魔值(调用animalProperties时不设置)REPAIRABLE- 设置为表示修复原料的标签键的HolderSetEQUIPPABLE- 设置槽位、装备声音、模型 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 是一个枚举,表示要渲染装备模型的层。虽然这些是非特定的,但它们由特定的实体渲染器通过层渲染器实现和读取。例如,HUMANOID 由 HumanoidArmorLayer 用于渲染头部、胸部和脚部;因此,任何对 HUMANOID 的使用都将使用该系统进行渲染。另一个例子是 WOLF_BODY 由 WolfArmorLayer 用于渲染身体盔甲。因此,如果使用现有的层类型(除非您的模组加载器支持枚举扩展,否则这是唯一的情况),请确保它们与现有的渲染器兼容。
$Layer 列表指定了在传入模型上渲染时使用的纹理和可染色选项。第一个参数指定纹理位置,相对于 textures/entity/equipment。第二个参数指定一个可选项,表示纹理是否可以被染色(通过 ItemTags#DYEABLE 与 DYED_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();
然后通过在 EntityRenderer 或 RenderLayer 的渲染函数中调用 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#renderTooltip、renderComponentTooltip现在有一个参数,用于接受工具提示背景和框架纹理的相对目录,如果为null则使用默认值net.minecraft.client.gui.screens.inventory.tooltip.TooltipRenderUtil#renderTooltipBackground现在有一个参数,用于接受工具提示背景和框架纹理的相对目录,如果为null则使用默认值net.minecraft.client.renderer.block.modelItemOverrides->BakedOverrides- 构造函数不再接受父级
BlockModel resolve->findOverride,不再接受后备模型
- 构造函数不再接受父级
ItemOverride、ItemOverride$Predicate现在是一个记录getPredicates已移除,使用predicatesgetModel->model
net.minecraft.client.renderer.entityEntityRenderDispatcher现在接受EquipmentModelSetEntityRendererProvider$ContextgetEquipmentModels- 获取当前装备纹理。getEquipmentRenderer- 获取装备的渲染器。
ItemRenderer不再接受Minecraft实例和TextureManagerTRIDENT_MODEL、SPYGLASS_MODEL现在是公开的TRIDENT_IN_HAND_MODEL、SPYGLASS_IN_HAND_MODEL已移除getItemModelShaper已移除renderBundleWithSelectedItem->renderBundleItem,不是一对一
net.minecraft.client.renderer.entity.layersCapeLayer现在接受EquipmentModelSetElytraLayer->WingsLayer- 构造函数现在接受
EquipmentLayerRenderer
- 构造函数现在接受
EquipmentLayerRenderer- 在提供的模型上渲染装备层的渲染器。HorseArmorLayer现在接受EquipmentLayerRendererHumanoidArmorLayer现在接受EquipmentLayerRenderer而不是ModelManagershouldRender- 返回可装备物品是否应在给定槽位中渲染。
LlamaDecorLayer现在接受EquipmentLayerRendererWolfArmorLayer现在接受EquipmentLayerRenderer
net.minecraft.client.renderer.entity.player.PlayerRenderer#getArmPose现在是私有的,被一个只接受HumanoidArm和PlayerRenderState的公共方法取代net.minecraft.client.resources.modelEquipmentModelSet- 从models/equipment加载EquipmentModel的资源监听器。ItemModel- 物品的模型。
net.minecraft.core.component.DataComponentsITEM_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.entityEquipmentSlot#getFilterFlag->getId- 还有一个方法
getFilterBit用于将 ID 转换为位掩码
- 还有一个方法
LivingEntitycanContinueToGlide->canGlide,不再接受ItemStackcanTakeItem被DataComponents#EQUIPPABLE取代canEquipWithDispenser- 返回堆栈在从发射器发射时是否可以装备。canDispenserEquipIntoSlot- 一个实体覆盖,指定发射器是否可以将装备放入给定槽位。isEquippableInSlot- 返回堆栈是否可以在给定槽位中装备。canGlideUsing- 实体是否可以使用提供的槽位中的堆栈滑翔。
MobcanReplaceCurrentItem现在接受EquipmentSlotisBodyArmorItem被DataComponents#EQUIPPABLE取代
net.minecraft.world.entity.animal.horseHorse#isBodyArmorItem被DataComponents#EQUIPPABLE取代Llama#isBodyArmorItem、getSwag被DataComponents#EQUIPPABLE取代
net.minecraft.world.itemAnimalArmorItem不再继承ArmorItem- 构造函数不再接受一个表示覆盖纹理的布尔值,因为现在这是
EquipmentModel的一部分 - 构造函数可以接受一个可选的
Holder<SoundEvent>作为装备声音 - 构造函数可以接受一个
boolean表示如果实体受伤,盔甲是否应该损坏 $BodyType现在接受允许穿戴盔甲的实体,而不是指向纹理的路径工厂
- 构造函数不再接受一个表示覆盖纹理的布尔值,因为现在这是
ArmorItem不再是可装备的- 基本上作为一个物品类,其剩余的唯一用途是在附魔时防止盔甲更换并获取关联的属性
$Type->ArmorType
ArmorMaterial->.equipment.ArmorMaterial- 基本上是一个虚拟记录,用于轻松处理应用关联的数据组件(
MAX_DAMAGE、ATTRIBUTE_MODIFIERS、ENCHANTABLE、EQUIPPABLE、REPAIRABLE)
- 基本上是一个虚拟记录,用于轻松处理应用关联的数据组件(
ArmorMaterials->.equipment.ArmorMaterialsBookItem、EnchantedBookItem->DataComponents#WRITTEN_BOOK_CONTENTBundleItem现在接受一个ResourceLocation作为模型,而不是仅仅字符串$Mutable#setSelectedItem->toggleSelectedItem
ComplexItem类已移除ElytraItem类已移除,现在只是带有DataComponents#GLIDER的物品Equippable->.equipment.Equippable,现在是一个定义物品如何装备的记录FoodOnAStackItem参数顺序已交换InstrumentItem参数顺序已交换ItemdescriptionId现在是 protectedgetDescription->getNamegetOrCreateDescriptionId已移除getDescriptionId(ItemStack)->DataComponents#ITEM_NAMEisEnchantable、getEnchantmentValue已移除isValidRepairItem已移除getDefaultAttributeModifiers已移除getDamageSource- 返回此物品对LivingEntity造成的伤害来源isComplex已移除$Propertiesequippable- 设置一个可装备组件,定义物品如何装备equippableUnswappable- 设置一个无法通过按键快捷方式交换的可装备组件。overrideDescription- 设置物品的翻译键。overrideModel- 设置模型资源位置。
getCraftingRemainingItem、hasCraftingRemainingItem->getCraftingRemainder
ItemNameBlockItem类已移除,只是一个带有useItemDescriptionPrefix属性的普通ItemItemStackITEM_NON_AIR_CODEC->Item#CODECisValidRepairItem- 返回堆栈是否可以由此堆栈修复。nextDamageWillBreak- 检查下一次受到的伤害是否会破坏物品。getDescriptionId->getItemName,不是一对一,因为现在它返回完整的组件
ShieldItem不再实现Equippable,通过DataComponents#EQUIPPABLE传入SignItem参数顺序已交换SmithingTemplateItem参数顺序已交换,移除了FeatureFlagStandingAndWallBlockItem参数顺序已交换AxeItem现在接受两个表示攻击伤害和攻击速度的浮点数DiggerItem现在接受两个表示攻击伤害和攻击速度的浮点数createAttributes->ToolMaterial#applyToolProperties
HoeItem现在接受两个表示攻击伤害和攻击速度的浮点数PickaxeItem现在接受两个表示攻击伤害和攻击速度的浮点数ShovelItem现在接受两个表示攻击伤害和攻击速度的浮点数SwordItem现在接受两个表示攻击伤害和攻击速度的浮点数createAttributes->ToolMaterial#applySwordProperties
Tier->ToolMaterialTieredItem类已移除Tiers常量存储在ToolMaterial上
net.minecraft.world.item.alchemy.Potion名称现在是必需的 -getName->name,不是一对一,因为这直接存储在药水上,没有任何其他处理net.minecraft.world.item.armortrim.*->.equipment.trim.*net.minecraft.world.item.componentTool中返回Tool$Rule的方法现在只接受HolderSet的方块,而不是列表或标签键DamageResistant- 一个组件,包含物品作为实体或穿戴时对其免疫的伤害类型标签
net.minecraft.world.item.enchantmentEnchantable- 物品附魔值的数据组件对象。Repairable- 可以修复此物品的物品的数据组件对象。
net.minecraft.world.level.blockAbstractSkullBlock不再实现EquippableEquipableCarvedPumpkinBlock类已移除,被DataComponents#EQUIPPABLE取代WoolCarpetBlock不再实现Equippable
交互结果
InteractionResult 已被完全修改,将所有内容包含在一系列密封的实现中。新的 InteractionResult 实现结合了 InteractionResultHolder 和 ItemInteractionResult,因此所有用途也已被替换。
InteractionResult 现在是一个接口,根据结果类型有四个实现。首先是 $Pass,表示交互检查应传递给调用堆栈中的下一个对象。$Fail,当用于物品和方块时,阻止调用堆栈中的任何进一步执行。对于实体,这将被忽略。最后,$TryEmptyHandInteraction 告诉调用堆栈尝试用空手应用点击,专门用于物品-方块交互。
还有 $Success,表示交互成功并且可以被消费。成功指定了两条信息:$SwingSource,表示挥动来源(CLIENT 或 SERVER)或 NONE(如果未指定),以及 $ItemContext,处理手中物品是否有交互,以及物品被转换成了什么。
这些对象都不应直接初始化。这些实现通过 InteractionResult 接口上的六个常量处理:
SUCCESS- 一个在客户端挥动手的$Success对象。SUCCESS_SERVER- 一个在服务器端挥动手的$Success对象。CONSUME- 一个不挥动手的$Success对象。FAIL- 一个$Fail对象。PASS- 一个$Pass对象。TRY_WITH_EMPTY_HAND- 一个$TryEmptyHandInteraction对象。
// 对于某个返回 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.CauldronInteractioninteract现在返回一个InteractionResultfillBucket、emptyBucket现在返回一个InteractionResult
net.minecraft.worldInteractionResultHolder、ItemInteractionResult->InteractionResult
net.minecraft.world.itemEquipable#swapWithEquipmentSlot现在返回一个InteractionResultItem#use、ItemStack#use现在返回一个InteractionResultItemUtils#startUsingInstantly现在返回一个InteractionResultJukeboxPlayable#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.itemInstrument接受一个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.trialspawnerTrialSpawner现在接受TrialSpawnerConfig的HoldercanSpawnInLevel现在接受一个ServerLevel
TrialSpawnerConfigCODEC->DIRECT_CODEC$Builder、builder- 试炼刷怪笼配置的构建器
配方提供者,数据提供者的“并非真正”
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.recipesRecipeOutput#includeRootAdvancement- 生成配方的根进度。RecipeProvider不再继承DataProvider- 构造函数接受查找提供者和一个
RecipeOutput,它们是 protected 字段 buildRecipes不接受任何参数- 所有生成方法都不接受
RecipeOutput并且是实例方法 $FamilyRecipeProvider- 通过传入结果方块和基础方块的Block为BlockFamily创建配方。$Runner- 一个DataProvider,通过createRecipeProvider构造RecipeProvider
- 构造函数接受查找提供者和一个
ShapedRecipeBuilder、ShapelessRecipeBuilder现在有私有构造函数,并接受物品的 holder getter
原料的转变
Ingredient 已被重新实现,使用 HolderSet 作为其基础,而不是其自己的内部 Ingredient$Value。这主要改变了 Ingredient#of 的调用,因为您需要为其提供 Item 对象或代表标签的 HolderSet。有关如何执行此操作的更多信息,请参阅持有者集部分。
net.minecraft.world.item.crafting.IngredientEMPTY->Ingredient#of,但默认用例不允许空原料CODEC已移除CODEC_NONEMPTY->CODECtestOptionalIngredient- 如果存在,则测试堆栈是否在原料内,否则默认为空检查。getItems->itemsgetStackingIds已移除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 过去之后。这方面的一个例子是 FoodProperties。ConsumableListener 只有一个方法 #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->CONSUMABLEnet.minecraft.world.entity.LivingEntitygetDrinkingSound、getEatingSound已移除,由ConsumeEffect处理triggerItemUseEffects已移除eat已移除
net.minecraft.world.entity.npc.WanderingTrader现在实现Consumable$OverrideConsumeSoundnet.minecraft.world.foodnet.minecraft.world.food.FoodDatatick现在接受一个ServerPlayergetLastFoodLevel、getExhaustionLevel、setExhaustion已移除
FoodProperties现在是一个ConsumableListenereatDurationTicks、eatSeconds->Consumable#consumeSecondsusingConvertsTo->DataComponents#USE_REMAINDER,effects->ConsumeEffect
net.minecraft.world.itemChorusFruitItem类已移除HoneyBottleItem类已移除ItemgetDrinkingSound、#getEatingSound已移除,由ConsumeEffect处理releaseUsing现在返回一个boolean表示是否成功释放$Properties#food现在可以接受一个Consumable用于自定义逻辑$Properties#usingConvertsTo- 使用后要转换成的物品。$Properties#useCooldown- 再次使用物品前等待的秒数。
ItemCooldowns现在接受ItemStack或ResourceLocation作为其方法的参数,而不仅仅是ItemgetCooldownGroup- 返回表示应用冷却时间的组的键
ItemStack#getDrinkingSound、getEatingSound已移除MilkBucketItem类已移除OminousBottleItem类已移除SuspiciousStewItem类已移除
net.minecraft.world.item.alchemy.PotionContents现在实现ConsumableListener- 构造函数接受一个可选的字符串,表示自定义名称的翻译键后缀
applyToLivingEntity- 将所有效果应用到提供的实体。getName- 通过将自定义名称附加到提供的内容字符串末尾来获取名称组件。
net.minecraft.world.item.componentConsumable- 一个定义何时可以消耗物品的数据组件。ConsumableListener- 应用于可被消耗的数据组件的接口,在消耗完成后执行。SuspiciousStewEffects现在实现ConsumableListenerUseCooldown- 一个定义如何应用堆栈冷却时间的数据组件。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$PropertiessetId- 设置物品的资源键,以获取默认描述和模型。此属性必须设置。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.propertiesBooleanProperty现在是 finalDirectionProperty类已移除EnumProperty现在是 finalcreate现在接受一个List而不是Collection
IntegerProperty现在是 finalProperty#getPossibleValues现在返回一个List而不是Collection
配方,现在采用注册表格式
配方已升级为数据包注册表,类似于战利品表的处理方式。它们仍然以相同的方式查询,只是简单地使用一个伪注册表支持的实例。一些更常见的变化是,RecipeHolder 可能被 RecipeDisplayId、RecipeDisplay 或 RecipeDisplayEntry 取代,如果不需要 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
}
配方显示
但是,配方如何理解应在配方书中显示什么?这属于两个新的静态注册表:RecipeDisplay 和 SlotDisplay。
SlotDisplay 表示配方中单个槽位内显示的内容。该显示只有一个方法(忽略类型):resolve。resolve 接受包含数据的 ContextMap 和 DisplayContentsFactory,后者接受将在该槽位中显示的堆栈和剩余物。SlotDisplay 还有许多辅助实现,例如 $Composite 接受一个显示列表,或 $ItemStackSlotDisplay 接受要显示的堆栈。该显示通过其 $Type 注册,该类型接受映射编解码器和流编解码器。
槽位还有通过 resolveForStacks 和 resolveForFirstStack 获取可显示的相关堆栈的方法。
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 可以通过 Ingredient、List<Ingredient> 或 List<Optional<Ingredient>> 使用 create 或 createFromOptionals 分别创建。
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.craftingIngredient#display- 返回显示此原料的SlotDisplay。PlacementInfo- 定义构造配方结果所需的所有原料。RecipegetToastSymbol->getCategoryIconItemgetIngredients、isIncomplete->placementInfogetIngredients->PlacementInfo#stackedRecipeContents,isIncomplete->PlacementInfo#isImpossibleToPlace
RecipeManager#getSynchronizedRecipes- 返回所有可以放置的配方并将它们发送到客户端。没有其他配方被同步。ShapedRecipePattern现在接受一个List<Optional<Ingredient>>而不是NonNullList<Ingredient>ShapelessRecipe现在接受一个List<Ingredient>而不是NonNullList<Ingredient>SmithingTransformRecipe、SmithingTrimRecipe现在接受Optional<Ingredient>而不是IngredientSuspiciousStewRecipe类已移除
配方变更
配方类本身有一些变化,它们反映了上述所有变化。首先,canCraftInDimensions 已移除,现在硬编码到匹配函数中。getResultItem 和 getCategoryIconItem 已被 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#recipe、addRecipe现在接受一个ResourceKey
net.minecraft.advancements.critereonPlayerPredicate现在接受一个ResourceKey作为配方映射$Builder#addRecipe现在接受一个ResourceKey
RecipeCraftedTriggertrigger现在接受一个ResourceKey$TriggerInstance现在接受一个ResourceKey$TriggerInstance#craftedItem、crafterCraftedItem现在接受一个ResourceKey
RecipeUnlockedTriggerunlocked现在接受一个ResourceKey$TriggerInstance现在接受一个ResourceKey
net.minecraft.clientClientRecipeBooksetupCollections->rebuildCollections,不是一对一getCollection(RecipeBookCategories)->getCollection(ExtendedRecipeBookCategory)add、remove- 处理在配方书中添加/移除要显示的配方条目。addHighLight、removeHighlight、hasHighlight- 处理当被玩家过滤或选择时条目是否高亮显示。clear- 清除已知和高亮显示的配方。
RecipeBookCategories#*_MISC->SearchRecipeBookCategory#*- 这也可以在方法中被
RecipeBookComponent$TabInfo、ExtendedRecipeBookCategory或RecipeBookCategory取代
- 这也可以在方法中被
net.minecraft.client.gui.components.toastsRecipeToast(RecipeHolder)->RecipeToast(),现在是私有的addOrUpdate现在接受一个RecipeDisplay而不是RecipeHolder
net.minecraft.client.gui.screens.inventory.AbstractFurnaceScreenrecipeBookComponent现在是私有的AbstractFurnaceScreen(T, AbstractFurnaceRecipeBookComponent, Inventory, Component, ResourceLocation, ResourceLocation, ResourceLocation)-AbstractFurnaceRecipeBookComponent已被Component取代,因为配方书不是在内部构造的,并且现在接受一个RecipeBookComponent$TabInfo列表
net.minecraft.client.gui.screens.recipebookAbstractFurnaceReipceBookComponent、BlastingFurnaceReipceBookComponent、SmeltingFurnaceReipceBookComponent、SmokingFurnaceReipceBookComponent->FurnaceReipceBookComponentGhostRecipe->GhostSlots,不是一对一,因为配方本身作为RecipeHolder存储在RecipeBookComponent的一个私有字段中addResult->setResult,不是一对一addIngredient->setIngredient,不是一对一setSlot、setInput、setResult现在接受一个ContextMap
OverlayRecipeComponent()->OverlayRecipeComponent(SlotSelectTime, boolean)init接受一个包含注册表数据的ContextMap以在组件中显示,以及一个boolean表示配方书是否正在过滤,而不是从Minecraft实例计算getLastRecipeClicked现在返回一个RecipeDisplayId$OverlayRecipeButton现在是一个抽象的包私有类,接受ContextMap$Pos现在是一个记录
RecipeBookComponent不再实现RecipeShownListener- 构造函数接受一个
$TabInfo列表,其中包含书中显示的标签页 init不再接受一个RecipeBookMenuinitVisuals现在是私有的initFilterButtonTextures现在是抽象的updateCollections现在接受另一个布尔值,表示书是否正在过滤renderTooltip现在接受一个可为 null 的Slot而不是一个表示槽位索引的intrenderGhostRecipe不再接受一个表示延迟时间的floatsetupGhostRecipe->fillGhostRecipe,不再接受要放置的List<Slot>,这存储在组件本身中selectMatchingRecipes不再接受RecipeBookrecipesShown现在接受一个RecipeDisplayIdsetupGhostRecipeSlots->fillGhostRecipe,接受ContextMap$TabInfo- 一个记录,表示配方书页面中要显示的图标和配方类别。
- 构造函数接受一个
RecipeBookPage()->RecipeBookPage(RecipeBookComponent, SlotSelectTime, boolean)updateCollections现在接受一个布尔值,表示书是否正在过滤getMinecraft已移除addListener已移除getLastRecipeClicked现在返回一个RecipeDisplayIdrecipesShown现在接受一个RecipeDisplayIdgetRecipeBook现在返回一个ClientRecipeBook
RecipeBookTabButton现在接受一个RecipeBookComponent$TabInfostartAnimation(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->selectRecipesgetRecipes、getDisplayRecipes->getSelectedRecipesregistryAccess、hasKnownRecipes、updateKnownRecipes已移除isCraftable现在接受一个RecipeDisplayIdhasFitting->hasAnySelectedgetRecipes现在返回一个RecipeDisplayEntry列表
RecipeShownListener类已移除RecipeUpdateListenergetRecipeBookComponent已移除fillGhostRecipe-> 给定RecipeDisplay填充幽灵配方
SearchRecipeBookCategory- 一个枚举,包含聚合类型的配方书类别。SlotSelectTime- 表示玩家选择的当前槽位索引。
net.minecraft.client.multiplayerClientPacketListener#getRecipeManager->recipes,返回RecipeAccessClientRecipeContainer- 当从服务器同步时,RecipeAccess的客户端实现。MultiPlayerGameMode#handlePlaceRecipe现在接受一个RecipeDisplayIdSessionSearchTrees#updateRecipes现在接受一个Level而不是RegistryAccess$Frozen
net.minecraft.client.player.LocalPlayer#removeRecipeHightlight现在接受一个RecipeDisplayIdnet.minecraft.commands.SharedSuggestionProvider#getRecipeNames已移除,因为它可以从注册表访问中查询net.minecraft.commands.arguments.ResourceLocationArgumentgetRecipe->ResourceKeyArgument#getRecipegetAdvancement->ResourceKeyArgument#getAdvancement
net.minecraft.commands.synchronization.SuggestionProviders#ALL_RECIPES已移除net.minecraft.core.component.DataComponents#RECIPES现在接受一个ResourceKey列表net.minecraft.data.recipesRecipeBuilder#save现在接受一个ResourceKey而不是ResourceLocationRecipeOutput#accept现在接受一个ResourceKey而不是ResourceLocationRecipeProvider#trimSmithing现在接受一个ResourceKey而不是ResourceLocation
net.minecraft.network.protocol.gameClientboundPlaceGhostRecipePacket- 一个包含容器 id 和RecipeDisplay的数据包ClientboundRecipeBookAddPacket- 向配方书添加条目的数据包ClientboundRecipeBookRemovePacket- 从配方书移除条目的数据包ClientboundRecipeBookSettingsPacket- 指定配方书设置的数据包ClientboundRecipePacket类已移除ClientboundUpdateRecipesPacket现在是一个记录,接受配方的属性集和切石机配方getRecipes已移除
ServerboundPlaceRecipePacket现在是一个记录ServerboundRecipeBookSeenRecipePacket现在是一个记录
net.minecraft.recipebookPlaceRecipe->PlaceRecipeHelperaddItemToSlot->$Output#addItemToSlotplaceRecipe现在接受一个Recipe而不是RecipeHolder- 有一个重载接受两个额外的 int,表示
ShapedRecipe的模式高度和宽度,或者只是重复前两个 int
- 有一个重载接受两个额外的 int,表示
RecipeBookadd、contains、remove->ServerRecipeBook#add、contains、removeaddHighlight、removeHighlight、willHighlight->ServerRecipeBook#addHighlight、removeHighlight、ClientRecipeBook#hasHighlightbookSettings现在是 protected
RecipeBookSettings#read、write现在是私有的ServerPlaceRecipe不再直接可访问,而是通过#placeRecipe作为RecipeBookMenu$PostPlaceAction访问和返回$CraftingMenuAccess- 定义如何与可放置配方菜单进行交互。
ServerRecipeBookfromNbt现在接受一个ResourceKey的谓词而不是RecipeManagercopyOverData- 从另一个配方书读取数据。$DisplayResolver- 通过传入RecipeDisplayEntry来解析要显示的配方
net.minecraft.stats.RecipeBook#isFiltering(RecipeBookMenu)已移除net.minecraft.world.entity.playerPlayer#awardRecipesByKey现在接受一个ResourceKey列表StackedItemContents#canCraft接受原料信息列表的重载
net.minecraft.world.inventoryAbstractCraftingMenu- 一个用于合成界面的菜单。AbstractFurnaceMenu现在接受RecipePropertySet键CraftingMenu#slotChangedCraftingGrid现在接受一个ServerLevel而不是LevelItemCombinerMenu现在接受一个ItemCombinerMenuSlotDefinitionmayPickup现在默认为true
ItemCombinerMenuSlotDefinition#hasSlot、getInputSlotIndexes已移除RecipeBookMenu不再接受任何泛型handlePlacement现在是抽象的,并返回一个$PostPlaceAction,接受一个额外的ServerLevel- 这将移除所有基本的配方放置调用,因为这将在内部由
ServerPlaceRecipe处理
- 这将移除所有基本的配方放置调用,因为这将在内部由
RecipeCraftingHolder#setRecipeUser不再接受一个LevelSmithingMenu#hasRecipeError- 返回当物品放置在库存中时配方是否有错误。
net.minecraft.world.item.craftingAbstractCookingRecipe现在实现SingleItemRecipe- 构造函数不再接受
RecipeType,因此用户需要覆盖getType方法 getExperience->experiencegetCookingTime->cookingTimefurnaceIcon- 返回炉子的图标。$Serializer- 烹饪配方序列化器实例的便利实现。
- 构造函数不再接受
CookingBookCategory现在有一个整数 idCraftingRecipe#defaultCrafingRemainder- 获取合成配方中应保留的堆栈。CustomRecipe$Serializer- 自定义配方序列化器实例的便利实现。ExtendedRecipeBookCategory- 表示配方书内类别的统一接口。Ingredient#optionalIngredientToDisplay- 将可选原料转换为SlotDisplay。Recipe#getRemainingItems->CraftingRecipe#getRemainingItemsRecipeAccess- 一个访问器,返回包含可用配方输入的属性集。RecipeBookCategory- 表示配方书内单个类别的对象。RecipeCache#get现在接受一个ServerLevel而不是LevelRecipeHolder现在接受一个ResourceKeyRecipeManager现在继承SimplePreparableReloadLsitener<RecipeMap>并实现RecipeAccessprepare- 从配方注册表创建配方映射logImpossibleRecipes、hasErrorsLoading已移除getRecipeFor现在接受一个ResourceKey,之前是ResourceLocationgetRecipesFor、getAllRecipesFor->RecipeMap#getRecipesForbyType已移除getRemainingItemsFor已移除byKey、byKeyTyped现在接受一个ResourceKeygetOrderedRecipes已移除getSynchronizedRecipes->getSynchronizedItemProperties、getSynchronizedStonecutterRecipes;不是一对一getRecipeIds已移除getRecipeFromDisplay- 根据其 id 获取配方显示信息。listDisplaysForRecipe- 接受要显示的配方的显示条目列表。replaceRecipes已移除$CachedCheck#getRecipeFor现在接受一个ServerLevel而不是Level$IngredientCollector- 一个从配方中提取原料并将其添加到RecipePropertySet的配方消费者$IngredientExtractor- 一个在存在时获取配方的原料的方法。$ServerDisplayInfo- 一个将显示条目链接到其配方持有者的记录。
RecipeMap- 一个通过配方类型和资源键映射配方持有者的类。RecipePropertySet- 一组可用作给定配方槽位输入的原料。用于只允许特定输入到屏幕上的槽位。SelectableRecipe- 一个包含槽位显示及其关联配方的记录。目前仅用于切石机菜单。SimpleCookingSerializer->AbstractCookingRecipe$SerializerSingleItemRecipe不再接受RecipeType或RecipeSerializeringredient、result、group现在是私有的input、result- 配方的槽位。
net.minecraft.world.item.crafting.displayDisplayContentsFactory- 用于接受配方内容的一个工厂。其子类型接受配方的堆栈和剩余物。RecipeDisplay- 用于显示配方内容的显示处理器。RecipeDisplayEntry- 一个将配方显示链接到其标识符、类别和合成需求的记录。RecipeDisplayId- 配方显示的标识符。SlotDisplay- 用于显示配方内槽位内容的显示处理器。SlotDisplayContext- 槽位显示使用的上下文键。
net.minecraft.world.level.Level#getRecipeManager->recipeAccess,在Level上返回RecipeAccess,但在ServerLevel上返回RecipeManagernet.minecraft.world.level.block.CrafterBlock#getPotentialResults现在接受一个ServerLevel而不是Levelnet.minecraft.world.level.block.entity.CampfireBlockEntitygetCookableRecipe已移除placeFood现在接受一个ServerLevel而不是Level
小幅迁移
以下是有用或有趣的增加、变更和移除的列表,它们不值得在入门文档中拥有自己的章节。
语言文件的移除与重命名
assets/minecraft/lang 中翻译键的所有移除和重命名现在显示在 deprecated.json 中。
条件,通过 HolderGetter 提供
在构造期间,所有条件构建器现在都接受一个 HolderGetter。虽然这可能不会被使用,但这是用来代替直接调用静态注册表来获取关联的 Holder 和 HolderSet。
net.minecraft.advancement.critereonBlockPredicate$Builder#ofConsumeItemTrigger$TriggerInstance#usedItemEntityEquipmentPredicate#captainPredicateEntityPredicate$Builder#ofEntityTypePredicate#ofItemPredicate$Builder#ofPlayerTrigger$TriggerInstance#walkOnBlockWithEquipmentShotCrossbowTrigger$TriggerInstance#shotCrossbowUsedTotemTrigger$TriggerInstance#usedToItem
MacosUtil#IS_MACOS
com.mojang.blaze3d.platform.MacosUtil#IS_MACOS 已被添加,以替换在渲染过程中指定布尔值。
com.mojang.blaze3d.pipelineRenderTarget#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.RenderSystemsetShaderFogStart、setShaderFogEnd、setShaderFogColor、setShaderFogShape->setShaderFoggetShaderFogStart、getShaderFogEnd、getShaderFogColor、getShaderFogShape->getShaderFog
net.minecraft.client.renderer.FogRenderersetupColor->computeFogColor,返回一个Vector4fsetupNoFog->FogParameters#NO_FOGsetupFog现在接受一个Vector4f作为颜色,并返回FogParameterslevelFogColor已移除
新标签
minecraft:banner_patternbordure_indentedfield_masoned
minecraft:blockbats_spawnable_onpale_oak_logs
minecraft:damage_typemace_smash
minecraft:itemdiamond_tool_materialsfurnace_minecart_fuelgold_tool_materialsiron_tool_materialsnetherite_tool_materialsvillager_picks_upwooden_tool_materialspiglin_safe_armorrepairs_leather_armorrepairs_chain_armorrepairs_iron_armorrepairs_gold_armorrepairs_diamond_armorrepairs_netherite_armorrepairs_turtle_helmetrepairs_wolf_armorduplicates_allaysbrewing_fuelpanda_eats_from_groundshulker_boxesbundlesmap_invisibility_equipmentpale_oak_logsgaze_disguise_equipment
minecraft:entity_typeboat
更智能的帧率限制
不再仅仅在玩家不在等级中或在屏幕或覆盖层中时限制帧率,而是根据不同的动作有不同的行为。这是通过 FramerateLimitTracker 使用 InactivityFpsLimit 完成的。这增加了两个额外的检查。如果窗口最小化,游戏以 10 fps 运行。如果用户一分钟没有输入,那么游戏以 30 fps 运行。十分钟没有输入后为 10 fps。
com.mojang.blaze3d.platform.FramerateLimitTracker- 一个根据设定值限制帧率的跟踪器。com.mojang.blaze3d.platform#Window#setFramerateLimit、getFramerateLimit已移除net.minecraft.clientInactivityFpsLimit- 一个枚举,定义了当窗口最小化或玩家离开键盘时如何限制 FPS。Minecraft#getFramerateLimitTracker- 返回帧率限制器。
燃料值
FuelValues 已取代 AbstractFurnaceBlockEntity 中的静态映射。它的功能与该映射相同,只是燃料值存储在 MinecraftServer 本身上,并可提供给单个 Level 实例。可以通过访问 MinecraftServer 或 Level 并调用 fuelValues 方法来获取映射。
net.minecraft.client.multiplayer.ClientPacketListener#fuelValues- 返回燃料的燃烧时间。net.minecraft.server.MinecraftServer#fuelValues- 返回燃料的燃烧时间。net.minecraft.server.level.Level#fuelValues- 返回燃料的燃烧时间。net.minecraft.world.level.block.entityAbstractFurnaceBlockEntityinvalidateCache、getFuel->Level#fuelValuesgetBurnDuration现在接受FuelValuesisFuel->FuelValues#isFuel
FuelValues- 一个包含燃料物品列表及其关联燃烧时间的类
发光强度
发光强度数据现在被烘焙到四边形中,可以使用 light_emission 标签添加到面中。
net.minecraft.client.renderer.block.modelBakedQuad现在接受一个int表示发光强度getLightEmission- 返回四边形的发光强度。
BlockElement现在接受一个int表示发光强度FaceBakery#bakeQuad现在接受一个int表示发光强度
地图纹理
地图纹理现在通过 MapTextureManager(处理动态纹理)和 MapRenderer(处理地图渲染)来处理。地图装饰仍然通过 map_decorations 精灵文件夹加载。
net.minecraft.clientMinecraftgetMapRenderer- 获取地图的渲染器。getMapTextureManager- 获取地图的纹理管理器。
net.minecraft.client.resources#MapTextureManager- 处理为地图创建动态纹理。net.minecraft.client.gui.MapRenderer->net.minecraft.client.renderer.MapRenderernet.minecraft.client.renderer#GameRenderer#getMapRenderer->Minecraft#getMapRenderer
朝向
随着红石线实验的加入,邻居变化带来了一个新类:Orientation。Orientation 实际上是两个方向和一个侧面偏置的组合。Orientation 用作一种方式,根据上下文的连接方向和偏置来传播更新。目前,这对不使用新红石线系统的人来说没有任何意义,因为所有对邻居方法的其他调用都将其设置为 null。然而,它确实提供了一种简单的方法来逐步传播行为。
net.minecraft.client.renderer.debug.RedstoneWireOrientationsRenderer- 红石线朝向的调试渲染器。net.minecraft.world.level.LevelupdateNeighborsAt- 使用指定的Orientation更新给定位置的邻居。updateNeighborsAtExceptFromFacing、neighborChanged现在接受一个Orientation
net.minecraft.world.level.block.RedStoneWireBlockgetBlockSignal- 返回方块信号的强度。
net.minecraft.world.level.block.state.BlockBehaviourneighborChanged、$BlockStateBase#handleNeighborChanged现在接受一个Orientation而不是邻居BlockPosupdateShape现在接受LevelReader、ScheduledTickAccess和RandomSource而不是LevelAccessor;Direction和BlockState参数的顺序已重新排列$BlockStateBase#updateShape现在接受LevelReader、ScheduledTickAccess和RandomSource而不是LevelAccessor;Direction和BlockState参数的顺序已重新排列
net.minecraft.world.level.redstoneCollectingNeighborUpdater$ShapeUpdate#state->neighborStateNeighborUpdaterneighborChanged、updateNeighborsAtExceptFromFacing、executeUpdate现在接受一个Orientation而不是邻居BlockPosexecuteShapeUpdate交换了BlockState和邻居BlockPos的顺序
Orientation- 方块上连接Direction的一组,并偏向正面或上面。RedstoneWireEvaluator- 传入和传出信号的强度评估器。
矿车行为
矿车现在有一个 MinecartBehavior 类,处理实体应如何移动和渲染。
net.minecraft.core.dispenser.MinecartDispenseItemBehavior- 定义矿车在从发射器发射时应如何表现。net.minecraft.world.entity.vehicleAbstractMinecartgetMinecartBehavior- 返回矿车的行为。exits现在是公开的isFirstTick- 返回这是否是实体存活的第一个刻。getCurrentBlockPosOrRailBelow- 获取矿车的当前位置或下方的铁轨。moveAlongTrack->makeStepAlongTracksetOnRails- 设置矿车是否在铁轨上。isFlipped、setFlipped- 返回矿车是否倒置。getRedstoneDirection- 返回红石供电的方向。isRedstoneConductor现在是公开的applyNaturalSlowdown现在返回要减速的向量。getPosOffs->MinecartBehavior#getPossetInitialPos- 设置矿车的初始位置。createMinecart在其创建中现在是抽象的,意味着它可以用于根据提供的参数创建任何矿车getMinecartType已移除getPickResult现在是抽象的$Type和getMinecartType被isRideable和isFurnace取代,不是一对一。
AbstractMinecartContainer(EntityType, double, double, double, Level)已移除MinecartBehavior- 包含实体在移动过程中应如何渲染和定位。MinecartFurnace#xPush、zPush->push
net.minecraft.world.level.block.state.properties.RailShape#isAscending->isSlopenet.minecraft.world.phys.shapes.MinecartCollisionContext- 处理矿车与其他碰撞对象碰撞的实体碰撞上下文。
爆——炸——!
Explosion 现在是一个定义爆炸元数据的接口。它不包含任何实际爆炸自身的方法。然而,ServerExplosion 仍然在内部用于处理等级爆炸等。
net.minecraft.world.levelExplosion->ServerExplosionExplosion- 一个定义爆炸应如何发生的接口。getDefaultDamageSource- 返回爆炸实例的默认伤害来源。shouldAffectBlocklikeEntities- 返回方块实体是否应受到爆炸影响。level- 获取ServerLevel
ExplosionDamageCalculator#getEntityDamageAmount现在接受一个额外的float表示所见百分比Level#explode不再返回任何内容
net.minecraft.world.level.block.Block#wasExploded现在接受一个ServerLevel而不是Levelnet.minecraft.world.level.block.state.BlockBehaviour#onExplosionHit、$BlockStateBase#onExplosionHit现在接受一个ServerLevel而不是Level
移除雕刻生成步骤
GenerationStep$Carving 已被移除,意味着所有 ConfiguredWorldCarver 都作为单个 HolderSet 提供。
// 在某个 BiomeGenerationSettings JSON 中
{
"carvers": [
// 在此处放置雕刻器
]
}
net.minecraft.world.level.biome.BiomeGenerationSettingsgetCarvers不再接受GenerationStep$Carving$Builder#addCarver不再接受GenerationStep$Carving$PlainBuilder#addCarver不再接受GenerationStep$Carving
net.minecraft.world.level.chunkChunkGenerator#applyCarvers不再接受GenerationStep$CarvingProtoChunk#getCarvingMask、getOrCreateCarvingMask、setCarvingMask不再接受GenerationStep$Carving
net.minecraft.world.level.levelgen.placementCarvingMaskPlacement类已移除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现在接受DynamicOps和Codec
- 构造函数现在是 protected,接受数据对象的编解码器、目录的字符串,以及一个可选的
连续执行器
ProcessorMailbox 和 ProcessorHandle 已被分别替换为 AbstractConsecutiveExecutor 和 TaskScheduler。它们在使用上基本相同,只是可能方法名称不同。
net.minecraft.util.threadProcessorMailbox->AbstractConsecutiveExecutor,不是一对一ConsecutiveExecutor将是等效的实现
PriorityConsecutiveExecutor- 一个指定调度时任务优先级的执行器。BlockableEventLoop#wrapRunnable->AbstractConsecutiveExecutor#wrapRunnableProcessorHandle->TaskScheduler,其中泛型是Runnable的子类型tell->scheduleask、askEither->scheduleWithResult,不是一对一of->wrapExecutor
StrictQueue不再接受F泛型,并使T成为Runnable的子类型pop现在返回一个Runnable$IntRunnable->$RunnableWithPriority
生物转化
通过 #convertTo 转化的生物,其逻辑由 ConversionType、ConversionParams 处理。ConversionType 是一个枚举,指示通过 #convert 将信息从一个生物复制到另一个生物时要应用的逻辑。常见属性通过 #convertCommon 处理,该方法在 #convert 方法内部调用。目前有两种类型:SINGLE,其中实体一对一地转换为另一个实体;以及 SPLIT_ON_DEATH,其中 Mob#convertTo 方法被多次调用,例如当史莱姆死亡时。ConversionParams 包含关于转化过程的元数据:类型、实体是否可以保留其装备或拾取战利品,以及实体所在的队伍。Mob#convertTo 还接受一个生物消费者,用于对实体本身应用任何最终化设置。
// 对于某个 Mob exampleMob
exampleMob.convertTo(
EntityType.SHEEP, // 要转化成的实体
new ConversionParams(
ConversionType.SINGLE, // 一对一
true, // 保留装备
false // 不保留拾取战利品
),
EntitySpawnReason.CONVERSION, // 实体生成原因
sheep -> {
// 对新建的转化实体执行任何其他设置
},
)
net.minecraft.world.entityConversionParams- 一个包含当生物转化为另一个实体时发生什么的设置的记录ConversionType- 一个枚举,定义一个生物如何转化为另一个生物。目前要么是SINGLE用于一对一,要么是SPLIT_ON_DEATH用于一对多(仅用于史莱姆)Mob#convertTo现在接受ConversionParams、一个可选的实体EntitySpawnReason(默认为CONVERSION),以及一个用于在转化后设置任何其他信息的生物消费者
末影珍珠加载区块
末影珍珠现在通过向区块源添加一个加载票并将实体存储在玩家上来加载它们穿过的区块。
net.minecraft.server.level.ServerPlayerregisterEnderPearl、deregisterEnderPearl、getEnderPearls- 处理玩家投掷的末影珍珠。registerAndUpdateEnderPearlTicket、placeEnderPearlTicket- 处理投掷的末影珍珠的区域加载票。
分析器与 Tracy 客户端
分析器已与 Minecraft 实例分离,现在通过 Profiler#get 获得。可以通过 Profiler#use 上的 try-resource 块添加一个新的分析器实例。此外,分析器添加了一个名为 Tracy 的新库,用于跟踪当前堆栈帧以及捕获屏幕上的图像,如果传入了关联的 --tracy 参数。这些部分可以拆分为“区域”,以更细粒度地区分正在发生的事情。
Profiler.get().push("section");
// 在此处执行代码
Profiler.get().pop();
com.mojang.blaze3d.systems.RenderSystem#flipFrame现在接受一个TracyFrameCapture,或nullnet.minecraft.client.Minecraft#getProfiler->Profiler#getnet.minecraft.client.main.GameConfig$GameData现在接受一个布尔值,表示是否通过 tracy 客户端捕获屏幕。net.minecraft.client.multiplayer.ClientLevel不再接受ProfilerFillernet.minecraft.server.MinecraftServer#getProfiler->Profiler#getnet.minecraft.server.packs.resources.PreparableReloadListener#reload不再接受ProfilerFillernet.minecraft.util.profilingProfiler- 一个用于管理当前活动ProfilerFiller的静态处理器。ProfilerFilleraddZoneText- 添加文本以在分析当前帧时标记。addZoneValue- 在分析当前帧时添加区域的值。setZoneColor- 在分析当前帧时设置区域的颜色。zone- 添加一个分析器部分,同时创建一个新区域来调用上述方法。tee->combine$CombinedProfileFiller- 一个写入多个分析器的分析器。
TracyZoneFiller- 由 tracy 客户端使用的分析器,用于跟踪当前正在分析的区域。Zone- 当前正在被 Tracy 分析和解释的部分。
net.minecraft.world.entity.ai.goal.GoalSelector不再接受提供的ProfilerFillernet.minecraft.world.levelLevel不再接受ProfilerFillergetProfiler、getProfilerSupplier->Profiler#get
PathNavigationRegion#getProfiler->Profiler#get
net.minecraft.world.ticks.LevelTicks不再接受ProfilerFiller
Tick节流器
为了防止玩家垃圾邮件某些动作,添加了 TickThrottler。节流器接受阈值和要添加到计数的增量。如果计数小于阈值,则可以发生该动作。计数每刻减少。
net.minecraft.util.TickThrottler- 一个用于限制某些动作发生频率的工具。
上下文键
战利品上下文参数已被上下文键取代,这只是对之前类的一个更通用的命名方案。这也导致上下文键用于可能有任意数据的其他上下文中。
简要描述,上下文键系统实际上是一个通用的类型化字典,其中每个 ContextKey 保存值类型,然后存储在 ContextMap 中的后备映射中。为了强制执行必需和可选参数,ContextMap 使用 ContextKeySet 构建,它定义了字典映射的键。
net.minecraft.advancements.critereon.CriterionValidator#validate现在接受一个ContextKeySet而不是LootContextParamSetnet.minecraft.data.loot.LootTableProvider$SubProviderEntry#paramSet现在接受一个ContextKeySet而不是LootContextParamSetnet.minecraft.util.contextContextKey- 一个表示对象的键。可以把它看作一个指定值类型的字典键。ContextKeySet- 一个键集,指示后备字典必须具有哪些键,以及可以指定的可选键。ContextMap- 上下文键到其类型化对象的映射。
net.minecraft.world.item.enchantmentConditionalEffect#codec现在接受一个ContextKeySet而不是LootContextParamSetTargetedConditionalEffect#codec现在接受一个ContextKeySet而不是LootContextParamSet
net.minecraft.world.level.storage.lootLootContexthasParam->hasParametergetParam->getParametergetParamOrNull-getOptionalParameter$EntityTraget#getParam现在返回一个ContextKey而不是LootContextParam
LootContextUser#getReferencedContextParams现在接受一组ContextKey而不是一组LootContextParamLootParams现在接受一个ContextMap而不是参数到对象的映射hasParam、getParameter、getOptionalParameter、getParamOrNull可以通过ContextMap以不同的名称访问$Builder#withParameter、withOptionalParameter、getParameter、getOptionalParameter现在接受一个ContextKey而不是LootContextParam$Builder#create现在接受一个ContextKeySet而不是LootContextParamSet
LootTablegetParameSet现在返回一个ContextKeySet而不是LootContextParamSet$Builder#setParamSet现在接受一个ContextKeySet而不是LootContextParamSet
ValidationContext现在接受一个ContextKeySet而不是LootContextParamSetvalidateUser->validateContextUsagesetParams-setContextKeySet
net.minecraft.world.level.storage.loot.functionsCopyComponentsFunction$Source#getReferencedContextParams现在接受一组ContextKey而不是一组LootContextParam
net.minecraft.world.level.storage.loot.parametersLootContextParam->net.minecraft.util.context.ContextKeyLootContextParamSet->net.minecraft.util.context.ContextKeySet
net.minecraft.world.level.storage.loot.providers.nbtContextNbtProvider$Getter#getReferencedContextParams现在接受一组ContextKey而不是一组LootContextParamNbtProvider#getReferencedContextParams现在接受一组ContextKey而不是一组LootContextParam
net.minecraft.world.level.storage.loot.providers.score.ScoreboardNameProvider#getReferencedContextParams现在接受一组ContextKey而不是一组LootContextParam
新增列表
com.mojang.blaze3d.framegraphFrameGraphBuilder- 一个构建帧图的构建器,定义渲染使用的资源和帧通道。FramePass- 一个接口,定义如何在帧图内读取/写入资源并执行它们进行渲染。
com.mojang.blaze3d.platformClientShutdownWatchdog- 为客户端关闭时创建的一个看门狗。NativeImage#getPixelsABGR- 以 ABGR 格式获取图像的像素。WindowisIconified- 返回窗口当前是否被图标化(通常最小化到任务栏)。setWindowCloseCallback- 设置窗口关闭时要运行的回调。
com.mojang.blaze3d.resourceCrossFrameResourcePool- 处理应跨多帧渲染的资源GraphicsResourceAllocator- 处理要渲染和移除的资源。RenderTargetDescriptor- 定义要分配和释放的渲染目标。ResourceDescriptor- 定义一个资源以及如何分配和释放它。ResourceHandle- 定义一个指向单个资源的指针。
com.mojang.blaze3d.systems.RenderSystem#overlayBlendFunc- 设置具有透明度的层之间的默认覆盖混合函数。com.mojang.blaze3d.vertexPoseStack#translate(Vec3)- 使用向量平移顶部姿势VertexConsumer#setNormal(PoseStack$Pose, Vec3)- 使用向量设置顶点的法线
net.minecraftOptionull#orElse- 如果第一个对象为 null,则返回第二个对象。TracingExecutor- 一个跟踪正在执行的类引用的堆栈帧的执行器。UtilallOf- 对所有提供的谓词或谓词列表进行 AND 操作。如果没有提供谓词,该方法将默认为true。anyOf- 对所有提供的谓词或谓词列表进行 OR 操作。如果没有提供谓词,该方法将默认为false。makeEnumMap- 根据枚举类和一个将枚举转换为值的函数创建一个枚举映射。
net.minecraft.advancements.critereonInputPredicate- 一个匹配玩家正在进行的输入的谓词。SheepPredicate- 用于实体是绵羊时的谓词。
net.minecraft.clientMinecraftsaveReport- 将崩溃报告保存到给定文件。triggerResourcePackRecovery- 当发生编译异常时尝试保存游戏的函数,目前在加载着色器时使用。
Options#highContrastBlockOutline- 启用时,在悬停在范围内方块上时提供更高的对比度。ScrollWheelHandler- 一个用于在鼠标滚轮滚动时存储信息的处理器。
ItemSlotMouseAction- 一个接口,定义鼠标悬停在槽位上时如何与槽位交互。net.minecraft.client.gui.componentsAbstractSelectionList#setSelectedIndex- 根据索引设置选中的条目。AbstractWidget#playButtonClickSound- 播放按钮点击声音。DebugScreenOverlay#getProfilerPieChart- 获取饼图分析器渲染器。
net.minecraft.client.gui.components.debugchart.AbstractDebugChart#getFullHeight- 返回渲染图表的高度。net.minecraft.client.gui.components.toastsToastgetWantedVisbility- 返回要渲染的吐司的可见性。update- 更新吐司内的数据。
TutorialToast有一个接受int表示显示时间(以毫秒为单位)的构造函数。
net.minecraft.client.gui.font.glyphs.BakedGlyphrenderChar- 以指定颜色渲染一个字符。$GlyphInstance- 一个带有其屏幕位置元数据的字形实例。
net.minecraft.client.gui.screensBackupConfirmScreen有一个构造函数,接受另一个Component表示清除缓存的提示。ScreengetFont- 返回当前用于渲染屏幕的字体。showsActiveEffects- 当为 true 时,显示当前应用于玩家的状态效果,假设相关屏幕添加了该功能。
net.minecraft.client.gui.screens.inventoryAbstractContainerScreenBACKGROUND_TEXTURE_WIDTH、BACKGROUND_TEXTURE_HEIGHT- 都设置为 256。addItemSlotMouseAction- 当悬停在槽位上时添加鼠标动作。renderSlots- 渲染菜单内的所有活动槽位。
AbstractRecipeBookScreen- 一个屏幕,具有从构造函数提供的可渲染和可交互的RecipeBookComponent。
net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent#showTooltipWithItemInHand- 返回当物品在玩家手中时是否应渲染工具提示。net.minecraft.client.gui.screens.worldselectionCreateWorldCallback- 一个接口,在给定当前屏幕、注册表、等级数据和路径目录的情况下创建世界。CreateWorldScreen#testWorld- 尝试使用提供的生成设置上下文打开世界创建屏幕。InitialWorldCreationOptions- 包含创建要生成的世界时设置的选项。WorldCreationContextMapper- 一个接口,从可用的资源重载器和注册表创建世界上下文。
net.minecraft.client.multiplayerClientChunkCachegetLoadedEmptySections- 返回已由游戏加载但没有数据的部分。
ClientLevelisTickingEntity- 返回实体是否在等级中Tick。setSectionRangeDirty- 将一个区域标记为脏,以便在持久性和网络调用期间更新。onSectionBecomingNonEmpty- 当部分有数据时更新该部分。
PlayerInfo#setTabListOrder、getTabListOrder- 处理玩家标签页中循环切换玩家的顺序。
net.minecraft.client.multiplayer.chat.report.ReportReason#getIncompatibleCategories- 获取对于给定类型无法报告的所有原因。net.minecraft.client.particle.TrailParticle- 一个从其当前位置到目标位置的拖尾粒子。net.minecraft.client.player.LocalPlayer#getDropSpamThrottler- 返回一个节流器,确定玩家何时可以丢弃下一个物品。net.minecract.client.rendererCloudRenderer- 处理云纹理数据的渲染和加载。DimensionSpecialEffects#isSunriseOrSunset- 返回维度时间是否代表游戏中的日出或日落。LevelEventHandler- 处理由Level#levelEvent方法发送的事件。LevelRenderergetCapturedFrustrum- 返回渲染器的平截头体框。getCloudRenderer- 返回天空盒中云的渲染器。onSectionBecomingNonEmpty- 当部分有数据时更新该部分。
LevelTargetBundle- 保存渲染阶段的资源句柄和渲染目标。LightTexturegetBrightness- 返回给定环境光和天空光的亮度。lightCoordsWithEmission- 返回打包的光照坐标。
RenderTypeentitySolidZOffsetForward- 获取一个实体的固体渲染类型,其中 z 从单个渲染对象偏移。flatClouds- 获取平坦云的渲染类型。debugTriangleFan- 获取调试三角形的渲染类型。vignette- 获取晕影类型。crosshair- 获取玩家准星的渲染类型。mojangLogo- 获取 Mojang 徽标的渲染类型
Octree- 一个用于定义部分应在平截头体中渲染顺序的遍历实现。ShapeRenderer- 用于在 Minecraft 等级中渲染基本形状的工具。SkyRenderer- 渲染天空。WeatherEffectRenderer- 渲染天气效果。WorldBorderRenderer- 渲染世界边界。
net.minecraft.client.rendererSectionOcclusionGraph#getOctree- 返回用于处理渲染部分遍历的八叉树。ViewArea#getCameraSectionPos- 获取相机的部分位置。
net.minecraft.client.renderer.culling.FrustumgetFrustumPoints- 将平截头体矩阵作为Vector4f数组返回。getCamX、getCamY、getCamZ- 返回平截头体相机坐标。
net.minecraft.client.renderer.chunk.CompileTaskDynamicQueue- 一个处理块渲染部分编译任务的同步队列。net.minecraft.client.renderer.debugChunkCullingDebugRenderer- 用于当块被剔除时的调试渲染器。DebugRendererrenderAfterTranslucents- 在半透明渲染后渲染块剔除渲染器。renderVoxelShape- 渲染体素形状的轮廓。toggleRenderOctree- 切换是否渲染OctreeDebugRenderer。
OctreeDebugRenderer- 渲染部分节点的顺序。
net.minecraft.client.renderer.texture.AbstractTexture#defaultBlur、getDefaultBlur- 返回正在应用的模糊是否是默认模糊。net.minecraft.client.resources.DefaultPlayerSkin#getDefaultSkin- 返回默认的PlayerSkin。net.minecraft.commands.CommandBuildContext#enabledFeatures- 返回功能标志net.minecraft.commands.arguments.selector.SelectorPattern- 一个记录,定义从某种模式解析的EntitySelector。net.minecraft.coreBlockPos#betweenClosed- 返回边界框内所有位置的迭代器。DirectiongetYRot- 返回给定方向的 Y 旋转。getNearest- 给定某个 XYZ 坐标,返回最近的方向,如果没有更近的方向则返回后备方向。getUnitVec3- 返回法线单位向量。$Axis#getPositive、getNegative、getDirections- 获取沿轴的方向。
GlobalPos#isCloseEnough- 返回此位置到另一个维度中块位置的距离是否在给定半径内。HolderLookup$ProviderlistRegistries- 返回每个注册表的注册表查找。allRegistriesLifecycle- 返回所有注册表组合的生命周期。
HolderSet#isBound- 返回集合是否绑定到某个值。Registry$PendingTags#size- 获取要加载的标签数量。Vec3i#distChessboard- 获取向量分量之间的最大绝对距离。
net.minecraft.core.componentDataComponentHolder#getAllOfType- 返回属于特定类类型的所有数据组件。DataComponentPredicatesomeOf- 构造一个数据组件谓词,其中提供的映射包含提供的组件类型。$Builder#expect- 添加我们应该期望数据组件具有某个值。
PatchedDataComponentMap#clearPatch- 清除对象上数据组件的所有补丁。
net.minecraft.core.particles.TargetColorParticleOption- 一个指定粒子目标位置和颜色的粒子选项。net.minecraft.data.DataProvidersaveAll- 使用提供的编解码器将资源位置到值的映射中的所有值写入PathProvider。saveStable- 使用给定的编解码器将值写入提供的路径。
net.minecraft.data.loot#BlockLootSubProvidercreateMossyCarpetBlockDrops- 为苔藓地毯块创建一个战利品表。createShearsOrSlikTouchOnlyDrop- 创建一个只有在用剪刀或带有精准采集附魔的物品挖掘时才能掉落其物品的战利品表。
net.minecraft.data.worldgen.Pools#createKey- 为模板池创建一个ResourceKey。net.minecraft.data.models.EquipmentModelProvider- 装备模型的模型提供者,仅包含原版引导。net.minecraft.data.info.DatapackStructureReport- 一个返回数据包结构的提供者。net.minecraft.gametest.frameworkGameTestHelperabsoluteAABB、relativeAABB- 在绝对坐标和相对于测试位置的坐标之间移动边界框assertEntityData- 断言提供的块位置的实体匹配谓词。hurt- 从某个来源对实体造成指定数量的伤害。kill- 杀死实体。
GameTestInfo#getTestOrigin- 获取测试的生成结构的原点。StructureUtils#getStartCorner- 获取要运行的测试的起始位置。
net.minecraft.networkFriendlyByteBufreadVec3、writeVec3- 读取和写入向量的静态方法。readContainerId、writeContainerId- 读取和写入菜单标识符的方法。readChunkPos、writeChunkPos- 读取和写入区块位置的方法。
StreamCodec#composite- 一个接受七个/八个参数的组合方法。
net.minecraft.network.codec.ByteBufCodecsCONTAINER_ID- 处理菜单标识符的流编解码器。ROTATION_BYTE- 打包到字节中的旋转。LONG- 长整型(64 字节)的流编解码器。OPTIONAL_VAR_INT- 可选整数的流编解码器,当不存在时序列化0,否则序列化存储值加一。- 使用此流编解码器无法正确发送
-1。
- 使用此流编解码器无法正确发送
net.minecraft.network.protocol.gameClientboundEntityPositionSyncPacket- 一个同步实体位置的数据包。ClientboundPlayerRotationPacket- 一个包含玩家旋转的数据包。
net.minecraft.serverMinecraftServertickConnection- Tick连接以处理数据包。reportPacketHandlingException- 报告尝试处理数据包时抛出的异常pauseWhileEmptySeconds- 确定当没有玩家在线时服务器应暂停多少刻。
SuppressedExceptionCollector- 一个处理被服务器抑制的异常的处理器。
net.minecraft.server.commands.LookAt- 一个接口,定义当命令运行时实体应该发生什么,通常是移动它以看向另一个实体。net.minecraft.server.levelChunkHolder#hasChangesToBroadcast- 返回区块内是否有任何更新要发送给客户端。ChunkTaskDispatcher- 区块的任务调度器。DistanceManagergetSpawnCandidateChunks- 返回玩家可以生成的所有区块。getTickingChunks- 返回当前正在Tick的所有区块。
ServerChunkCache#onChunkReadyToSend- 将一个区块持有者添加到队列中进行广播。ServerEntityGetter- 一个在ServerLevel上操作的实体获取器接口实现。- 替换了
EntityGetter中缺失的方法
- 替换了
ServerPlayergetTabListOrder- 处理玩家标签页中循环切换玩家的顺序。getLastClientInput、setLastClientInput、getLastClientMoveIntent- 处理服务器玩家如何解释客户端脉冲。commandSource- 返回玩家的命令源。createCommandSourceStack- 创建发出命令的玩家的源堆栈。
ThrottlingChunkTaskDispatcher- 一个设置最大同时执行区块数的区块任务调度器。TickingTracker#getTickingChunks- 返回当前正在Tick的所有区块。
net.minecraft.server.packs.repository.PackRepository#isAbleToClearAnyPack- 重建选定的资源包并返回它是否与当前选定的资源包不同。net.minecraft.resources.DependantName- 一个将某个注册表对象ResourceKey映射到一个值的引用对象。类似于Holder,但作为一个函数式接口。net.minecraft.tags.TagKey#streamCodec- 为标签键构造一个流编解码器。net.minecraft.utilARGB#vector3fFromRGB24- 使用整数的低 24 位创建一个包含 RGB 分量的Vector3f。BinaryAnimator- 一个使用缓动函数在两个状态之间进行动画的基本动画器。ExtraCodecsNON_NEGATIVE_FLOAT- 一个验证值不能为负的浮点编解码器。RGB_COLOR_CODEC- 一个表示 RGB 颜色的整数、浮点数或三维向量浮点编解码器。nonEmptyMap- 一个验证映射不为空的映射编解码器。
MthwrapDegrees- 将度数设置为 (-180, 180] 范围内的值。lerp- 使用分量在两个向量之间进行线性插值。length- 获取空间中 2D 点的长度。easeInOutSine- 一个从 (0,0) 开始,每 pi 在 1 和 0 之间交替的余弦函数。packDegrees、unpackDegrees- 将float形式的度数存储到byte中并读取。
RandomSource#triangle- 使用三角形分布在两个float(包含,不包含)之间返回一个随机的float。StringRepresentable$EnumCodec#byName- 通过字符串名称获取枚举,如果为 null 则获取提供的供应商值。TriState- 一个表示三种可能状态的枚举:true、false 或 default。
net.minecraft.util.datafix.ExtraDataFixUtilspatchSubType- 将第一个类型中的第二个类型重写为第三个类型。blockState- 返回方块状态的动态实例fixStringField- 修改动态中的字符串字段。
net.minecraft.util.thread.BlockableEventLookupBLOCK_TIME_NANOS- 返回事件将阻塞线程的时间(以纳秒为单位)。isNonRecoverable- 返回异常是否可以恢复。
net.minecraft.world.damagesource.DamageSourcesenderPearl- 返回末影珍珠击中时的伤害来源。mace- 返回一个实体直接用狼牙棒击中另一个实体时的伤害来源。
net.minecraft.world.entityEntityapplyEffectsFromBlocks- 通过Block#entityInside或硬编码检查(如雪或雨)应用方块产生的任何效果。isAffectedByBlocks- 返回实体在内部时是否受方块影响。checkInsideBlocks- 获取玩家经过的所有方块,并检查实体是否在一个方块内,如果存在则将其添加到一个集合中。oldPosition、setOldPosAndrot、setOldPos、setOldRot- 更新实体最后位置和旋转的辅助方法。getXRot、getYRot- 返回给定部分刻下实体的线性插值旋转。isAlliedTo(Entity)- 返回实体是否与此实体结盟。teleportSetPosition- 通过DimensionTransition设置被传送实体的位置和旋转数据getLootTable- 返回实体应使用的战利品表的ResourceKey(如果存在)。isControlledByOrIsLocalPlayer- 返回实体是否是本地玩家或由本地玩家控制。shouldPlayLavaHurtSound- 当为true时,实体受到熔岩伤害时播放熔岩伤害声音。onRemoval- 当实体被移除时调用的方法。cancelLerp- 停止任何插值移动。forceSetRotation- 设置实体的旋转。isControlledByClient- 返回实体是否由客户端输入控制。
EntityTypegetDefaultLootTable现在返回一个Optional,以防战利品表不存在$Builder#noLootTable- 设置实体类型在死亡时不生成战利品。$Builder#build现在接受实体类型的资源键
EntitySelector#CAN_BE_PICKED- 返回一个选择器,获取所有不在旁观模式下的可拾取实体。LivingEntitydropFromShearingLootTable- 使用剪毛上下文解析战利品表。getItemHeldByArm- 返回特定手臂持有的堆栈。getEffectiveGravity- 返回应用于实体的重力。canContinueToGlide- 返回实体是否仍能在空中滑翔。getItemBlockingWith- 返回玩家当前正在格挡的堆栈。canPickUpLoot- 返回实体是否可以拾取物品。dropFromGiftLootTable- 使用礼物上下文解析战利品表。handleExtraItemsCreatedOnUse- 处理活体实体因使用另一个物品而获得新物品时的情况。isLookingAtMe- 检查提供的实体是否正在看着这个实体。
PositionMoveRotation- 用于处理上下文中实体的位置和旋转的辅助工具。WalkAnimationState#stop- 停止实体的行走动画。
net.minecraft.world.entity.ai.attributesAttributeInstancegetPermanentModifiers- 返回应用于实体的所有永久修饰符。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.PathNavigationupdatePathfinderMaxVisitedNodes- 更新实体可以访问的最大节点数。setRequiredPathLength- 设置实体必须采取的最小路径长度。getMaxPathLength- 返回实体可以采取的最大路径长度。
net.minecraft.world.entity.ai.sensingPlayerSensor#getFollowDistance- 返回此实体的跟随距离。Sensor#wasEntityAttackableLastNTicks- 返回一个谓词,检查实体在指定的刻数内是否可攻击。
net.minecraft.world.entity.ai.village.poi.PoiRecord#pack、PoiSection#pack- 打包必要的兴趣点信息。这只移除了脏 runnable。net.minecraft.world.entity.animalAgeableWaterCreature- 一个有年龄状态的水生生物。AnimalcreateAnimalAttributes- 为动物创建属性提供者。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.playerInventoryisUsableForCrafting- 返回状态是否可以用于合成配方。createInventoryUpdatePacket- 创建用于更新库存中物品的数据包。
PlayerhandleCreativeModeItemDrop- 处理玩家从创造模式丢弃物品时的情况。shouldRotateWithMinecart- 返回玩家是否也应随矿车旋转。canDropItems- 当为true时,玩家可以从菜单中丢弃物品。getPermissionLevel、hasPermissions- 返回玩家的权限。
StackedContents- 保存内容列表及其关联大小。$Output- 一个接口,定义在选择内容时如何接受它们。
net.minecraft.world.entity.projectile.ProjectilespawnProjectileFromRotation- 生成一个投射物并从给定的旋转角度射出。spawnProjectileUsingShoot- 生成一个投射物并通过#shoot设置初始冲量。spawnProjectile- 生成一个投射物。applyOnProjectileSpawned- 根据给定的等级和ItemStack应用任何额外的配置。onItemBreak- 处理发射投射物的物品损坏时的情况。shouldBounceOnWorldBorder- 返回投射物是否应弹离世界边界。setOwnerThroughUUID- 通过查询其 UUID 来设置投射物的拥有者。$ProjectileFactory- 定义投射物如何从某个ItemStack由实体生成。
net.minecraft.world.entity.vehicleAbstractBoat- 一个代表船的实体。AbstractChestBoat- 一个代表带有某种库存的船的实体。ChestRaft- 一个代表带有某种库存的木筏的实体。Raft- 一个代表木筏的实体。
net.minecraft.world.inventory.AbstractContainerMenuaddInventoryHotbarSlots- 在给定的 x 和 y 位置为给定容器添加快捷栏槽位。addInventoryExtendedSlots- 在给定的 x 和 y 位置为给定容器添加玩家库存槽位。addStandardInventorySlots- 在给定的 x 和 y 位置为给定容器在其正常位置添加快捷栏和玩家库存槽位。setSelectedBundleItemIndex- 切换槽位中选中的捆绑包。
net.minecraft.world.itemBundleItemgetOpenBundleModelFrontLocation、getOpenBundleModelBackLocation- 返回捆绑包的模型位置。toggleSelectedItem、hasSelectedItem、getSelectedItem、getSelectedItemStack- 处理捆绑包内的物品选择。getNumberOfItemsToShow- 确定一次显示的捆绑包中的物品数量。getByColor- 处理从捆绑包到染色捆绑包的可用链接。getAllBundleItemColors- 返回所有染色捆绑包的流。
ItemStackclearComponents- 清除对堆栈所做的补丁,而不是物品组件。isBroken- 返回堆栈是否已损坏。hurtWithoutBreaking- 损坏堆栈而不使其损坏。getStyledHoverName- 获取堆栈的样式化名称组件。
net.minecraft.world.item.component.BundleContentscanItemBeInBundle- 物品是否可以放入捆绑包。getNumberOfItemsToShow- 确定一次显示的捆绑包中的物品数量。hasSelectedItem、getSelectedItem- 处理捆绑包内的物品选择。
net.minecraft.world.item.enchantment.EnchantmentHelpercreateBook- 创建一个附魔书堆栈。doPostAttackEffectsWithItemSourceOnBreak- 在物品损坏时,在攻击后应用附魔。
net.minecraft.world.levelBlockCollisions有一个接受CollisionContext的构造函数BlockGetter#boxTraverseBlocks- 返回在给定边界框中沿向量遍历的位置的迭代器。CollisionGetternoCollision- 返回实体与方块、实体以及如果提供的boolean为true则液体之间是否存在碰撞。getBlockAndLiquidCollisions- 返回边界框内实体的方块和液体碰撞。clipIncludingBorder- 获取指定剪辑上下文的方块命中结果,必要时由世界边界钳制。
EmptyBlockAndTintGetter- 一个虚拟的BlockAndTintGetter实例。GameType#isValidId- 检查 id 是否与现有的游戏类型匹配。LevelHeightAccessor#isInsideBuildHeight- 返回指定的 Y 坐标是否在等级的边界内。
net.minecraft.world.level.blockBlock#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.stateBlockBehaviourgetEntityInsideCollisionShape、$BlockStateBase#getEntityInsideCollisionShape- 确定实体在内部时方块的体素形状。$Properties#overrideDescription- 设置方块名称的翻译键。
StateHoldergetValueOrElse- 返回属性的值,否则返回提供的默认值。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.chunkChunkAccess#canBeSerialized- 返回 true,允许将区块写入磁盘。ChunkSource#onSectionEmptinessChanged- 当部分有数据时更新该部分。LevelChunkSectioncopy- 制作区块部分的浅拷贝。setUnsavedListener- 添加一个监听器,每当区块被标记为脏时,该监听器接受区块位置。$UnsavedListener- 一个当区块被标记为脏时被调用的区块位置消费者。
PalettedContainerRO#copy- 创建PalettedContainer的浅拷贝。UpgradeData#copy- 创建UpgradeData的深拷贝。
net.minecraft.world.level.chunk.storage.IOWorker#store- 将区块的写入存储到工作器中。net.minecraft.world.level.levelgenSurfaceRules$Context#getSeaLevel、SurfaceSystem#getSeaLevel- 获取生成器设置的海平面。WorldOptions#testWorldWithRandomSeed- 使用随机生成的种子创建一个测试世界。
net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecorator$Context#checkBlock- 检查给定位置的方块是否匹配谓词。net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplategetJigsaws- 返回在给定位置和旋转下具有给定旋转的拼图方块。getJointType- 返回拼图方块的连接类型。$JigsawBlockInfo- 一个包含拼图方块块信息的记录。- 大多数涉及拼图的方法已将
$StructureBlockInfo替换为$JigsawBlockInfo。
- 大多数涉及拼图的方法已将
net.minecraft.world.level.lighting.LayerLightSectionStorage#lightOnInColumn- 返回零节点部分位置是否有光。net.minecraft.world.level.pathfinder.PathFinder#setMaxVisitedNodes- 设置可以访问的最大节点数。net.minecraft.world.level.portalDimensionTransition#withRotation- 更新实体的生成旋转。PortalShape#findAnyShape- 找到一个可以位于给定方块位置并面向特定方向的PortalShape。
net.minecraft.world.physAABBclip- 在给定边界框内剪辑向量,如果没有交点则返回空 optional。collidedAlongVector- 返回此框是否与列表中提供的边界框之一沿提供的移动向量发生碰撞。getBottomCenter- 获取边界框底部中心的向量。
Vec3add、subtract- 平移向量并返回一个新对象。horizontal- 返回向量的水平分量。projectedOn- 获取表示此向量投影到另一个向量上的单位向量。
net.minecraft.world.phys.shapesCollisionContextof(Entity, boolean)- 创建一个新的实体碰撞上下文,其中boolean确定实体是否总是可以站在提供的流体状态上。getCollisionShape- 返回碰撞到的碰撞形状。
VoxelShape#move(Vec3)- 将体素形状按提供的向量偏移。
net.minecraft.world.ticks.ScheduledTick#toSavedTick- 将计划Tick转换为保存的Tick。
变更列表
F3 + F现在切换雾渲染com.mojang.blaze3d.platformNativeImagegetPixelRGBA、setPixelRGBA现在是私有的。它们分别被getPixel和setPixel取代getPixelsRGBA->getPixels
Window#updateDisplay现在接受一个TraceyFrrameCapture,或null
net.minecraft.UtilbackgroundExecutor、ioPool和nonCriticalIoPool现在返回TracingExecutor而不是ExecutorServicewrapThreadWithTaskName->runNamed,参数翻转,无返回值
net.minecraft.advancements.critereonKilledByCrossbowTrigger->KilledByArrowTrigger,不是一对一,接受相关的堆栈PlayerPredicate现在可以匹配玩家的输入
net.minecraft.clientMinecraftdebugFpsMeterKeyPress->ProfilerPieChart#profilerPieChartKeyPress,通过Minecraft#getDebugOverlay然后DebugScreenOverlay#getProfilerPieChart获得getTimer->getDeltaTrackergetToasts->getToastManager
Options#setModelPart现在是公开的,取代了toggleModelPart但不广播更改ParticleStatus->net.minecraft.server.level.ParticleStatus
net.minecraft.client.animation.KeyframeAnimations#animate现在接受一个Model而不是HierarchicalModelnet.minecraft.client.gui.FontdrawInBatch(String, float, float, int, boolean, Matrix4f, MultiBufferSource, Font.DisplayMode, int, int, boolean)已移除,应使用Component替代- 还有一个委托,在
Component的drawInBatch方法中默认将逆深度布尔值设置为 true
- 还有一个委托,在
$StringRenderOutput现在接受Font、一个可选背景颜色,以及一个布尔值,表示在绘制文本时是否应使用逆深度$StringRenderOutput#finish现在是包私有的
net.minecraft.client.gui.componentsAbstractSelectionListreplaceEntries现在是公开的getRowTop、getRowBottom现在是公开的
PlayerFaceRenderer#draw(GuiGraphics, ResourceLocation, int, int, int, int)接受一个PlayerSkin而不是ResourceLocation
net.minecraft.client.gui.components.toastsToastToast$Visibility render(GuiGraphics, ToastComponent, long)->void render(GuiGraphics, Font, long)slotCount-occupiedSlotCount
ToastComponent->ToastManager
net.minecraft.client.gui.font.glyphs.BakedGlyphrender现在接受一个表示颜色的整数而不是四个浮点数,并且是私有的renderChar是公共替代,接受$GlyphInstance、Matrix4f、VertexConsumer和颜色整数
$Effect是一个记录,现在接受一个表示颜色的整数而不是四个浮点数
net.minecraft.client.gui.screensLoadingOverlay#MOJANG_STUDIOS_LOGO_LOCATION现在是公开的ScreenrenderBlurredBackground(float)->renderBlurredBackground()wrapScreenError->fillCrashDetails,不是一对一,因为它只添加相关的崩溃信息,而不是实际抛出错误
net.minecraft.client.gui.screens.inventoryAbstractContainerScreen#renderSlotHighlight->renderSlotHighlightBack、renderSlotHighlightFront,现在是私有的BookEditScreen现在接受WritableBookContentAbstractSignEditScreensign现在是 protectedrenderSignBackground不再接受BlockState
EffectRenderingInventoryScreen->Screen#hasActiveEffects、EffectsInInventory。不是一对一,因为EffectsInInventory现在作为一个辅助类,帮助屏幕在指定位置渲染其效果。
net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponentgetHeight()->getHeight(Font)renderImage现在接受渲染工具提示的int宽度和高度
net.minecraft.client.gui.screens.recipebookGhostSlots#render不再接受 x 和 y 偏移。RecipeBookComponent不再接受 x 和 y 偏移。
net.minecraft.client.gui.screens.reporting.ReportReasonSelectionScreen现在接受一个ReportTypenet.minecraft.client.gui.screens.worldselectionCreateWorldScreen$DataPackReloadCookie->DataPackReloadCookieopenFresh现在有一个接受CreateWorldCallback的重载
WorldCreationContext现在接受InitialWorldCreationOptionsWorldOpenFlows#createFreshLevel接受一个Function<HolderLookup.Provider, WorldDimensions>而不是Function<RegistryAccess, WorldDimensions>
net.minecraft.client.gui.spectator.SpectatorMenuItem#renderIcon现在接受一个float而不是int来表示 alpha 值net.minecraft.client.multiplayerClientLevel现在接受一个int表示海平面getSkyColor现在返回一个int而不是Vec3getCloudColor现在返回一个int而不是Vec3setGameTime、setDayTime->setTimeFromServer
TagCollector->RegistryDataCollector$TagCollector,现在是包私有的
net.minecraft.client.playerAbstractClientPlayer#getFieldOfViewModifier现在接受一个布尔值表示相机是否在第一人称,以及一个浮点数表示部分刻Input->ClientInput和net.minecraft.world.entity.player.InputKeyboardInput现在继承ClientInputLocalPlayer#input现在是ClientInput
net.minecraft.client.rendererDimensionSpecialEffects#getSunriseColor->getSunriseOrSunsetColorGameRendererprocessBlurEffect不再接受部分刻floatgetFov返回float而不是doublegetProjectionMatrix现在接受float而不是double
ItemModelShapershapes现在是私有的getItemModel(Item)已移除getItemModel(ResourceLocation)- 获取与提供的ResourceLocation关联的烘焙模型。register已移除getModelManager已移除invalidateCache- 清除模型映射。
LevelRendererrenderSnowAndRain->WeatherEffectRenderertickRain->tickParticlesrenderLevel现在接受一个GraphicsResourceAllocatorrenderClouds->CloudRendereraddParticle现在是公开的globalLevelEvent->LevelEventHandlerentityTarget->entityOutlineTarget$TransparencyShaderException不再接受可抛出原因
SectionOcclusionGraphonSectionCompiled->schedulePropagationFromupdate现在接受一个保存当前加载的部分节点的LongOpenHashSet$GraphState现在是包私有的addSectionsInFrustum现在接受一个列表以添加渲染部分
ShapeRenderer#renderShape现在接受一个整数表示颜色,而不是四个浮点数ViewArearepositionCamera现在接受SectionPos而不是两个doublegetRenderSectionAt->getRenderSection
net.minecraft.client.renderer.blockentityBannerRenderer#renderPatterns现在接受一个boolean确定要使用的闪光渲染类型- 构造
LayerDefinition的*Renderer类现在已移动到它们关联的*Model类 SignRenderer$SignModel->SignModel
net.minecraft.client.renderer.chunk.SectionRenderDispatcher现在接受一个TracingExecutor而不是仅仅一个Executor$CompiledSection#hasNoRenderableLayers->hasRenderableLayers$RenderSection现在接受一个编译的long表示部分节点setOrigin->setSectionNodegetRelativeOrigin->getNeighborSectionNodecancelTasks现在不返回任何内容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现在接受Frustumnet.minecraft.client.renderer.texture.atlas.sources.PalettedPermutations#loadPaletteEntryFromImage现在是私有的net.minecraft.client.tutorialTutorialaddTimedToast、#removeTimedToast、$TimedToast->TutorialToast参数onInput接受一个ClientInput而不是Input
TutorialStepInstanceonInput接受一个ClientInput而不是Input
net.minecraft.coreDirectiongetNearest->getApproximateNearestgetNormal->getUnitVec3i
HolderGetter$Provider#get不再接受注册表键,而是从ResourceKey读取它HolderLookup$Provider现在实现HolderGetter$ProviderasGetterLookup已移除,因为该接口是一个HolderGetter$ProviderlistRegistries->listRegistryKeys
Registry现在实现HolderLookup$RegistryLookupgetTags只返回命名持有者集的流asTagAddingLookup->prepareTagReloadbindTags->WritabelRegistry#bindTagget->getValuegetOrThrow->getValueOrThrowgetHolder->getgetHolderOrThrow->getOrThrowholders->listElementsgetTag->getholderOwner、asLookup已移除,因为Registry是它们的实例
RegistryAccessregistry->lookupregistryOrThrow->lookupOrThrow
RegistrySynchronization#NETWORKABLE_REGISTRIES->isNetworkable
net.minecraft.core.cauldron.CauldronInteractionFILL_WATER->fillWaterInteraction,现在是私有的FILL_LAVA->fillLavaInteraction,现在是私有的FILL_POWDER_SNOW->fillPowderSnowInteraction,现在是私有的SHULKER_BOX->shulkerBoxInteraction,现在是私有的BANNER->bannerInteraction,现在是私有的DYED_ITEM->dyedItemIteration,现在是私有的
net.minecraft.core.dispenser.BoatDispenseItemBehavior现在接受要生成的EntityType而不是变体和是否有箱子的布尔值net.minecraft.core.particles.DustColorTransitionOptions、DustParticleOptions现在接受表示 RGB 值的整数而不是Vector3f。net.minecraft.data.lootBlockLootSubProviderHAS_SHEARS->hasShearscreateShearsOnlyDrop现在是一个实例方法
EntityLootSubProviderkilledByFrog、killedByFrogVariant现在接受EntityType注册表的获取器createSheepTable->createSheepDispatchPool,不是一对一,因为该表被替换为一个池构建器,给定一个染料颜色到战利品表的映射
net.minecraft.gametest.frameworkGameTestHelper#assertEntityPresent、assertEntityNotPresent接受一个边界框而不是两个向量GameTestInfo#getOrCalculateNorthwestCorner现在是公开的
net.minecraft.network.chat.Component#score现在接受一个SelectorPatternnet.minecraft.network.chat.contents.ScoreContents、SelectorContents现在是一个记录net.minecraft.network.protocol.login.ClientboundGameProfilePacket->ClientboundLoginFinishedPacketnet.minecraft.network.protocol.gameClientboundMoveEntityPacket#getyRot、getxRot现在返回一个float表示度数ClientboundPlayerPositionPacket现在是一个记录,接受一个表示变化的PositionMoverotationrelativeArguments->relativesyRot、xRot->ClientboundPalyerRotationPacket
ClientboundSetTimePacket现在是一个记录ClientboundRotateHeadPacket#getYHeadRot现在返回一个float表示度数ClientboundTeleportEntityPacket现在是一个记录,其中必要的参数被传入数据包而不是实体ServerboundPlayerInputPacket现在是一个记录,接受一个Input
net.minecraft.resources.RegistryDataLoader$Loader#loadFromNetwork现在接受一个$NetworkedRegistryData,其中包含打包的注册表条目net.minecraft.serverMinecraftServer不再实现AutoCloseabletickChildren现在是 protectedwrapRunnable现在是公开的
ReloadableServerRegistries#reload现在接受一个待处理标签的列表,并返回一个$LoadResult而不是一个分层注册表访问ReloadableServerResourcesloadResources现在接受一个待处理标签的列表和服务器ExecutorupdateRegistryTags->updateStaticRegistryTags
ServerFunctionLibrary#getTag、ServerFunctionManager#getTag返回一个命令函数列表
net.minecraft.server.levelChunkHolderblockChanged、sectionLightChanged现在返回boolean表示信息是否已更改addSaveDependency现在是 protected,GenerationChunkHolder中的一个方法
ChunkTaskPriorityQueue不再接受泛型- 构造函数不再接受最大任务数
submit现在接受一个Runnable而不是Optionalpop返回一个$TasksForChunk而不是原始的Stream
ChunkTaskPriorityQueueSorter->ChunkTaskDispatcherServerPlayerteleportTo接受一个boolean,决定是否应设置相机INTERACTION_DISTANCE_VERIFICATION_BUFFER->BLOCK_INTERACTION_DISTANCE_VERIFICATION_BUFFER- 还拆分为
ENTITY_INTERACTION_DISTANCE_VERIFICATION_BUFFER,设置为 3.0
- 还拆分为
findRespawnPositionAndUseSpawnBlock现在处理TeleportTransition
TextFilterClient->ServerTextFilterThreadedLevelLightEngine现在接受一个ConsecutiveExecutor和ChunkTaskDispatcher而不是分别接受ProcessorMailbox和ProcessorHandle
net.minecraft.server.packs.resources.ProfiledReloadInstance$State现在是一个记录net.minecraft.sounds.SoundEvent现在是一个记录net.minecraft.tagsTagEntry$Lookup#element现在接受一个boolean表示元素是否必需TagLoader现在接受一个$ElementLookup,其功能与之前的函数参数相同build现在返回一个列表的值loadAndBuild->loadTagsFromNetwork、loadTagsForExistingRegistries、loadTagsForRegistry、buildUpdatedLookups
TagNetworkSerialization$NetworkPayloadsize->isEmptyapplyToRegistry->resolve
net.minecraft.utilFastColor->ARGBscaleRGB重载,带有一个 alpha 整数和三个浮点数。
Mth#color->ARGB#color
net.minecraft.util.profiling.metrics.MetricCategory#MAIL_BOXES->CONSECUTIVE_EXECUTORSnet.minecraft.util.threadBlockableEventLoop#waitForTasks现在是 protectedProcessorMailbox不再实现AutoCloseable
net.minecraft.util.worldupdate.WorldUpgrader实现AutoCloseablenet.minecraft.world.LockCode现在接受一个ItemPredicate而不是表示物品名称的StringaddToTag、fromTag现在接受一个HolderLookup$Provider
net.minecraft.world.effectMobEffect#applyEffectTick、applyInstantenousEffect、onMobRemoved、onMobHurt现在接受ServerLevelMobEffectInstance#onMobRemoved、onMobHurt现在接受ServerLevel
net.minecraft.world.entityAgeableMob$AgeableMobGroupData现在有一个公共构造函数AnimationState#getAccumulatedTime->getTimeInMillisEntity不再实现CommandSourcesetOnGroundWithMovement现在接受一个额外的boolean表示是否有任何水平碰撞。getInputVector现在是 protectedisAlliedTo(Entity)->considersEntityAsAllyteleportTo现在接受一个额外的boolean,决定是否应设置相机checkInsideBlocks()->recordMovementThroughBlocks,不是一对一,因为它接受移动向量checkInsideBlocks(Set<BlockState>)->collectBlockCollidedWith,现在是私有的kill现在接受ServerLevelhurt已被标记为已弃用,将被hurtServer和hurtClient取代hurtOrSimulate作为一个辅助方法,决定调用哪一个,也被标记为已弃用
spawnAtLocation现在接受ServerLevelisInvulnerableTo->isInvulnerableToBase,现在是 protected 和 finalisInvulnerableTo已移至LivingEntity#isInvulnerableTo
teleportSetPosition现在是公开的,接受PositionMoveRotation和Relative集而不是DimensionTransitioncreateCommandSourceStack->createCommandSourceStackForNameResolution,不是一对一,因为它接受ServerLevelmayInteract现在接受ServerLevel而不是仅仅LevelsetOldRot现在是公开的changeDimension->teleport,给定TeleportTransition返回ServerPlayercanChangeDimensions->canTeleport
EntitySpawnReason#SPAWN_EGG->SPAWN_ITEM_USE,不是一对一,因为这表示实体可以从任何物品生成EntityTypecreate、loadEntityRecursive、loadEntitiesRecursive、loadStaticEntity现在接受一个EntitySpawnReason*StackConfig现在接受一个Level而不是ServerLevel
EquipmentTable现在有一个构造函数,接受一个单一的float表示所有装备槽位的槽位掉落几率MobSpawnType->EntitySpawnReasonLeashable#tickLeash现在接受ServerLevelLivingEntitygetScale现在是 finalonAttributeUpdated现在是 protectedactiveLocationDependentEnchantments现在接受一个EquipmentSlothandleRelativeFrictionAndCalculateMovement现在是私有的updateFallFlying现在是 protectedonEffectRemoved->onEffectsRemovedspawnItemParticles现在是公开的getLootTable->Entity#getLootTable,包装在 optional 中getBaseExperienceReward现在接受ServerLeveltriggerOnDeathMobEffects现在接受ServerLevelcanAttack已移除dropEquipment现在接受ServerLeveldropExperience现在接受ServerLeveldropFromLootTable现在接受ServerLevelactuallyHurt、doHurtTarget现在接受ServerLevelhasLineOfSight重载,带有剪辑上下文和眼睛 Y 提供者makePoofParticles现在是公开的
MobpickUpItem、wantsToPickUp现在接受ServerLevelequipItemIfPossible现在接受ServerLevelcustomServerAiStep现在接受ServerLeveldropPreservedEquipment现在接受ServerLevel
NeutralMobisAngryAt、isAngryAtAllPlayers现在接受ServerLevelplayerDied现在接受ServerLevel
PortalProcessor#getPortalDestination现在返回一个TeleportTransitionPositionMoveRotationof(ClientboundPlayerPositionPacket)->ofEntityUsingLerpTarget(Entity)of(DimensionTransition)->of(TeleportTransition)
Shearable#shear现在接受ServerLevel和正在剪毛的ItemStackRelativeMovement->Relative,扩展为包含增量移动WalkAnimationState#update现在接受一个额外的float表示移动时的位置缩放。
net.minecraft.world.entity.ai.behaviorStartAttacking现在接受一个$TargetFinder和一个$StartAttackingCondition- 两者都是函数式接口,取代了之前的函数/谓词,但多了一个
ServerLevel参数
- 两者都是函数式接口,取代了之前的函数/谓词,但多了一个
StopAttackingIfTargetInvalid现在接受一个$TargetErasedCallback和/或一个$StopAttackCondition- 两者都是函数式接口,取代了之前的消费者/谓词,但多了一个
ServerLevel参数
- 两者都是函数式接口,取代了之前的消费者/谓词,但多了一个
MeleeAttack#create现在可以接受一个谓词来测试生物Swim现在接受一个代表生物的泛型
net.minecraft.world.entity.ai.control.LookControl#rotateTowards->Control#rotateTowardsnet.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal现在接受一个$Selector- 这是一个函数式接口,取代了之前的谓词,但多了一个
ServerLevel参数
- 这是一个函数式接口,取代了之前的谓词,但多了一个
net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities现在接受一个ServerLevelnet.minecraft.world.entity.ai.sensingNearestLivingEntitySensorradiusXZ、radiusY->Attributes#FOLLOW_RANGEisMatchingEntity现在接受一个ServerLevel
SensorTARGETING_RANGE现在是私有的isEntityTargetable、isEntityAttackable、isEntityAttackableIgnoringLineOfSight现在接受一个ServerLevelwasEntityAttackableLastNTicks、rememberPositives现在处理BiPredicate而不是Predicate
net.minecraft.world.entity.ai.targeting.TargetingConditionsselector现在接受一个$Selector- 这是一个函数式接口,取代了之前的谓词,但多了一个
ServerLevel参数
- 这是一个函数式接口,取代了之前的谓词,但多了一个
test现在接受一个ServerLevel
net.minecraft.world.entity.ai.village.poi.PoiRecord#codec、PoiSection#codec->$Packed#CODECnet.minecraft.world.entity.animalFox$Type->$VariantMushroomCow$MushroomType->$Variant$Variant不再接受战利品表
Salmon现在有一个表示其大小的变体WolfgetBodyRollAngle->#getShakeAnim,不是一对一,因为角度是在渲染状态下计算的hasArmor已移除
net.minecraft.world.entity.animal.horse.AbstractHorse#followMommy现在接受一个ServerLevelnet.minecraft.world.entity.boss.enderdragon.EnderDragon#onCrystalDestroyed现在接受一个ServerLevelnet.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance#doServerTick现在接受一个ServerLevelnet.minecraft.world.entity.boss.wither.WitherBoss#getHead*Rot->getHead*Rots,返回所有旋转而不是仅返回提供的索引net.minecraft.world.entity.decorationArmorStand默认旋转现在是公开的isShowArms->showArmsisNoBasePlate->showBasePlate
PaintingVariant现在接受一个标题和作者Component
net.minecraft.world.entity.item.ItemEntity#getSpin现在是静态的net.minecraft.world.entity.monster.Monster#isPreventingPlayerRest现在接受一个ServerLevelnet.minecraft.world.entity.monster.breeze.Breeze#getSnoutYPosition->getFiringYPositionnet.minecraft.world.entity.monster.hoglin.HoglinBase#hurtAndThrowTarget现在接受一个ServerLevelnet.minecraft.world.entity.monster.piglin.PiglinAi#isWearingGold->#isWearingSafeArmornet.minecraft.world.entity.npc.InventoryCarrier#pickUpItem现在接受一个ServerLevelnet.minecraft.world.entity.playerPlayer#disableShield现在接受要应用冷却时间的堆栈InventoryfindSlotMatchingUnusedItem->findSlotMatchingCraftingIngredientswapPaint->setSelectedHotbarSlotStackedContents->StackedItemContents
net.minecraft.world.entity.projectileAbstractArrow#inGround->IN_GROUND,现在是一个EntityDataAccessor- 可通过
isInGround和setInGround受保护访问
- 可通过
ThrowableItemProjectile现在可以接受一个被投掷物品的ItemStack
net.minecraft.world.entity.raid.Raid#getLeaderBannerInstance->getOminousBannerInstancenet.minecraft.world.entity.vehicleBoat$Type现在接受提供的船物品和物品的翻译键,但不再接受它们由什么木板制成ContainerEntity*LootTable*->ContainerLootTablechestVehicleDestroyed现在接受一个ServerLevel
VehicleEntitydestroy现在接受一个ServerLevelgetDropItem现在是 protected
net.minecraft.world.itemBoatItem现在接受一个EntityType而不是变体和是否有箱子的布尔值ItemStack#hurtEnemy、postHurtEnemy现在接受一个LivingEntity而不是PlayerSmithingTemplateItem现在接受Item.Properties而不是硬编码,对于静态初始化器也是如此UseAnim->ItemUseAnimation
net.minecraft.world.item.crafting.ShulkerBoxColoring->TransmuteRecipe,扩展为将存储在物品上的任何数据复制到结果物品net.minecraft.world.item.enchantment.EnchantmentHelperonProjectileSpawned现在接受一个Projectile而不是AbstractArrow
net.minecraft.world.item.enchantment.effects.DamageItem->ChangeItemDamagenet.minecraft.world.levelGameRules在任何类型的构造期间都接受一个FeatureFlagSet$IntegerValue#create接受一个FeatureFlagSet$Type接受一个FeatureFlagSet
LevelsetSpawnSettings不再接受一个boolean来决定是否生成友好生物getGameRules->ServerLevel#getGameRules
LevelAccessor现在实现ScheduledTickAccess,一个现在包含原本在LevelAccessor上的Tick调度方法的接口neighborShapeChanged交换了BlockState和邻居BlockPos参数的顺序
LevelHeightAccessorgetMinBuildHeight->getMinYgetMaxBuildHeight->getMaxY,该值比之前版本少一getMinSection->getMinSectionYgetMaxSection->getMaxSectionY,该值比之前版本少一
NaturalSpawner#spawnForChunk已被拆分为两个方法:getFilteredSpawningCategories和spawnForChunk
net.minecraft.world.level.biome#Biome#getPrecipitationAt、coldEnoughToSnow、warmEnoughToRain、shouldMeltFrozenOceanIcebergSlightly现在接受一个int表示生物群系的基础高度net.minecraft.world.level.blockBlockshouldRenderFace接受正在检查的面的相对状态,不再传入BlockGetter或BlockPos。updateEntityAfterFallOn->updateEntityMovementAfterFallOn$BlockStatePairKey->FlowingFluid$BlockStatePairKey,现在是包私有的getDescriptionId->BlockBehaviour#getDescriptionId,也是一个 protected 字段descriptionId
ChestBlock构造函数交换了参数顺序Portal#getPortalDestination现在返回TeleportTransition
net.minecraft.world.level.block.entityAbstractFurnaceBlockEntity#serverTick现在接受一个ServerLevel而不是LevelBrushableBlockEntitybrush现在接受等级和执行刷洗行为的堆栈unpackLootTable现在是私有的checkReset现在接受服务器等级
net.minecraft.world.level.block.stateBlockBehaviourgetOcclusionShape、getLightBlock、propagatesSkylightDown只接受BlockState,不接受BlockGetter或BlockPosgetLootTable现在返回一个Optional,也是一个 protected 字段drops$BlockStateBase#getOcclusionShape、getLightBlock、getFaceOcclusionShape、propagatesSkylightDown、isSolidRender不再接受BlockGetter或BlockPos$BlockStateBase#getOffset不再接受BlockGetter$OffsetFunction#evaluate不再接受BlockGetter$Properties#dropsLike->overrideLootTable
StateHolder#findNextInCollection现在接受一个List而不是Collection
net.minecraft.world.level.chunkChunkAccessaddPackedPostProcess现在接受一个ShortList而不是一个shortgetTicksForSerialization现在接受一个long表示游戏时间unsaved现在是私有的setUnsaved->markUnsaved、tryMarkSaved$TicksToSave->$PackedTicks
ChunkSource#setSpawnSettings不再接受一个boolean来决定是否生成友好生物LevelChunk#postProcessGeneration现在接受一个ServerLevelPalette#copy现在接受一个PaletteResize
net.minecraft.world.level.chunk.status.WorldGenContext现在接受一个Executor或主线程,而不是一个处理器句柄邮箱- 构造函数还接受一个
LevelChunk$UnsavedListener,用于当区块被标记为脏时
- 构造函数还接受一个
net.minecraft.world.level.chunk.storageChunkSerializer->SerializableChunkDataChunkStorage#write现在接受一个提供的CompoundTag而不是实例本身SectionStorage现在接受第二个泛型,表示存储数据的打包形式- 构造函数现在接受打包编解码器、一个将存储转换为打包格式的函数,以及一个将打包数据和脏 runnable 转换回存储的函数。
net.minecraft.world.level.levelgenAquifer$FluidStatus现在是一个记录WorldDimensions#withOverworld现在接受一个HolderLookup而不是Registry本身BlendingData现在有一个打包和解包状态,用于将内部数据序列化为一个简单对象
net.minecraft.world.level.levelgen.material.MaterialRuleList现在接受一个数组而不是一个列表net.minecraft.world.level.levelgen.placement.PlacementContext#getMinBuildHeight->getMinYnet.minecraft.world.level.levelgen.structure.pools.StructurePoolElement#getShuffledJigsawBlocks现在返回StructureTemplate$JigsawBlockInfonet.minecraft.world.level.lightingLevelLightEngine#lightOnInSection->lightOnInColumnLightEnginehasDifferentLightProperties、getOcclusionShape不再接受BlockGetter或BlockPosgetOpacity不再接受BlockPosshapeOccludes不再接受两个long表示打包的位置
net.minecraft.world.level.materialFlowingFluidspread现在接受当前位置的BlockStategetSlopeDistance之前的参数已被合并到一个$SpreadContext对象中spread、getNewLiquid、canConvertToSource、getSpread现在接受一个ServerLevel
Fluidtick现在接受当前位置的BlockStatetick和randomTick现在接受ServerLevel
FluidStatetick现在接受当前位置的BlockStatetick和randomTick现在接受ServerLevel
MapColor#calculateRGBColor->calculateARGBColor
net.minecraft.world.level.portalDimensionTransition->TeleportTransitionpos->positionspeed->deltaMovement- 构造函数现在可以接受一组
Relatives来指示位置应相对于另一个位置移动的哪些运动
PortalShape#createPortalBlocks现在接受一个LevelAccessor
net.minecraft.world.level.saveddata.SavedData#save(File, HolderLookup$Provider)现在返回CompoundTag,不在方法中将数据写入文件net.minecraft.world.level.storageDimensionDataStorage现在实现AutoCloseable- 构造函数接受一个
Path而不是File save->scheduleSave和saveAndJoin
- 构造函数接受一个
LevelData#getGameRules->ServerLevelData#getGameRules
net.minecraft.world.phys.BlockHitResult现在接受一个布尔值表示是否击中了世界边界- 添加了两个辅助方法
hitBorder、isWorldBorderHit
- 添加了两个辅助方法
net.minecraft.world.ticksProtoChunkTicks#load现在接受一个保存的Tick列表SavedTick#loadTickList现在返回一个保存的Tick列表,而不是消费它们SerializableTickContainer#save->pack
移除列表
com.mojang.blaze3d.Blaze3Dprocessrender
com.mojang.blaze3d.pipeline.RenderPipeline- 被
com.mojang.blaze3d.framegraph.*和com.mojang.blaze3d.resources.*取代
- 被
com.mojang.blaze3d.platform.NativeImagesetPixelLuminancegetRedOrLuminance、getGreenOrLuminance、getBlueOrLuminanceblendPixelasByteArray
com.mojang.blaze3d.systems.RenderSystemglGenBuffersglGenVertexArrays_setShaderTextureapplyModelViewMatrix
net.minecraft.Util#wrapThreadWithTaskName(String, Supplier)net.minecraft.advancements.critereon.EntitySubPredicates#BOATnet.minecraft.client.Options#setKeynet.minecraft.client.gui.screens.inventory.EnchantmentScreen#timenet.minecraft.client.multiplayerClientCommonPacketListenerImpl#strictErrorHandlingClientLevel#isLightUpdateQueueEmptyCommonListenerCookie#strictErrorHandling
net.minecraft.client.particle.ParticleRenderType#PARTICLE_SHEET_LITnet.minecraft.client.rendererGameRenderer#resetProjectionMatrixLevelRendererplayJukeboxSongclear
PostChaingetTempTarget、addTempTarget
PostPasssetOrthoMatrixgetFilterMode
net.minecraft.client.renderer.block.model.BlockModel#fromStringnet.minecraft.client.renderer.textureAbstractTexture#blur、mipmapTextureManager#bindForSetup
net.minecraft.commands.arguments.coordinates.WorldCoordinates#currentnet.minecraft.coreDirection#fromDeltaRegistry#getOrCreateTag、getTagNames、resetTags
net.minecraft.server.MinecraftServerisSpawningAnimalsareNpcsEnabled
net.minecraft.server.levelGenerationChunkHolder#getGenerationRefCountServerPlayersetPlayerInputteleportTo(ServerLevel, double, double, double, float, float, boolean)
net.minecraft.tagsTagManagerTagManagerSerialization$TagOutput
net.minecraft.world.entityAnimationState#updateTimeEntitywalkDist0、walkDistwasOnFiretryCheckInsideBlocks
EntitySelector$MobCanWearArmorEntitySelector
net.minecraft.world.entity.ai.sensingBreezeAttackEntitySensor#BREEZE_SENSOR_RADIUSTemptingSensor#TEMPTATION_RANGE
net.minecraft.world.entity.animalCat#getTextureIdSquid#setMovementVectorWolf#isWet
net.minecraft.world.entity.boss.dragon.EnderDragongetLatencyPosgetHeadPartYOffset
net.minecraft.world.entity.monster.Zombie#supportsBreakDoorGoalnet.minecraft.world.entity.npc.Villager#setChasing、isChasingnet.minecraft.world.entity.projectileAbstractArrow#shotFromCrossbowThrowableProjectile(EntityType, LivingEntity, Level)
net.minecraft.world.itemBannerPatternItem#getDisplayNameItemStack#LIST_STREAM_CODEC
net.minecraft.world.level.BlockGetter#getMaxLightLevelnet.minecraft.world.level.block.entity.JigsawBlockEntity$JointType#byNamenet.minecraft.world.level.block.state.BlockBehaviour#isOcclusionShapeFullBlocknet.minecraft.world.level.chunk.ChunkAccess#setBlendingDatanet.minecraft.world.level.storage.loot.LootDataType#deserializenet.minecraft.world.phys.AABB#getBottomCenternet.minecraft.world.phys.shapes.Shapes#getFaceShapenet.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 字段关联的 MapCodec。calculate 接受当前的 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,我们有阈值 3 和 5,则会选择 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 字段关联的 MapCodec。get 接受堆栈、等级、实体和种子值,并返回一个任意浮点数,供范围分发模型解释。
然后,需要将 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$Type。get 接受堆栈、等级、实体、种子值和显示上下文,并返回一个可编码的对象,供选择模型解释。
然后,需要将 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 字段关联的 MapCodec。get 接受堆栈、等级、实体、种子值和显示上下文,并返回一个布尔值,分别由 on_true 和 on_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,并使用其 type 的 MapCodec 进行注册。然后,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"
}
}
}
渲染物品
现在,通过 ItemModelResolver 和 ItemStackRenderState 来渲染物品。这与 EntityRenderState 的工作方式类似:首先,ItemModelResolver 设置 ItemStackRenderState,然后通过 ItemStackRenderState#render 渲染状态。
让我们从 ItemStackRenderState 开始。对于渲染,我们只关心以下方法:isEmpty、isGui3d、usesBlockLight、transform 和 render。isEmpty 用于确定堆栈是否应该被渲染。然后,isGui3d、usesBlockLight 和 transform 在其关联的上下文中用于正确定位要渲染的堆栈。最后,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 中的更多方法,虽然您通常不会使用它们,但了解它们很有用:ensureCapacity 和 newLayer。这两个方法负责确保有足够的 ItemStackRenderState$LayerRenderState,如果您碰巧同时叠加多个模型的话。实际上,每次您计划在未烘焙模型中渲染某些东西时,都应该调用 newLayer。如果您计划将多个东西叠加在一起渲染,那么应该在调用 newLayer 之前使用计划渲染的层数设置 ensureCapacity。
一个物品模型定义由 ItemModel 组成,它在功能上定义了一个“烘焙模型”及其用于序列化的 ItemModel$Unbaked。
未烘焙变体有两个方法:bake,用于创建 ItemModel;以及 type,它引用要注册到 ItemModels#ID_MAPPER 的 MapCodec,但该字段默认是私有的,因此需要一些访问更改或反射。bake 接受 $BakingContext,其中包含用于获取 BakedModel 的 ModelBaker、用于实体模型的 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.clientClientBootstrap- 注册支持客户端的映射;目前用于物品模型定义。MinecraftgetEquipmentModels已移除,只能在EntityRendererProvider$Context#getEquipmentAssets中直接访问getItemModelResolver- 返回用于解析当前要在ItemStackRenderState$LayerRenderState中渲染的模型的更新器。
KeyMapping#get- 根据其翻译键获取按键映射。
net.minecraft.client.color.itemConstant- 用于对物品纹理进行染色的常量。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.rendererBlockEntityWithoutLevelRenderer类已移除,被NoDataSpecialModelRenderer数据生成系统取代ItemInHandRenderer现在接受ItemModelResolverItemModelShaper已移除,因为这些方法在ModelManager中可用SheetsgetBedMaterial- 根据染料颜色获取床的材质。colorToResourceMaterial- 获取染料颜色的资源位置。createBedMaterial- 根据染料颜色或资源位置创建床的材质。getShulkerBoxMaterial- 根据染料颜色获取潜影盒的材质。colorToShulkerMaterial- 获取潜影盒的染料颜色的资源位置。createShulkerMaterial- 根据染料颜色或资源位置创建潜影盒的材质。chestMaterial- 使用给定的资源位置为箱子创建一个新的材质。
SpecialBlockModelRenderer- 方块到物品变体特殊渲染器的映射。
net.minecraft.client.renderer.block.BlockRenderDispatcher现在接受一个提供的SpecialBlockModelRenderer而不是BlockEntityWithoutLevelRenderernet.minecraft.client.renderer.block.modelBakedOverrides类已移除,被RangeSelectItemModelProperty数据生成系统取代BlockModel现在接受TextureSlots$Data而不是材质映射,并且不再接受ItemOverride列表MISSING_MATERIAL已移除,被minecraft:missingno取代textureMap->textureSlots,现在是私有的,不是一对一parent现在是私有的,不是一对一parentLocation现在是私有的hasAmbientOcclusion->getAmbientOcclusionisResolved已移除getOverrides已移除getParent- 返回未烘焙的父模型。getTextureSlots- 返回模型的纹理数据。getElements现在是包私有的$GuiLight->UnbakedModel$GuiLight
FaceBakerybakeQuad现在是静态的calculateFacing现在是私有的
ItemModelGenerator现在实现UnbakedModelItemOverride类已移除,被RangeSelectItemModelProperty数据生成系统取代ItemTransforms现在是一个记录hasTransform已移除
TextureSlots- 一个处理模型内纹理映射的类。数据从$Data读取,并作为$SlotContents存储,直到在烘焙过程中解析为Material。UnbakedBlockStateModel现在继承ResolvableModel而不是UnbakedModelbake- 将方块状态烘焙到其可选择的模型中。
Variant现在是一个记录
net.minecraft.client.renderer.blockentityBannerRenderer现在有一个接受EntityModelSet的重载构造函数renderInHand- 渲染旗帜的物品模型。
BedRenderer现在有一个接受EntityModelSet的重载构造函数renderInHand- 渲染床的物品模型。
BlockEntityRenderDispatcher(Font, EntityModelSet, Supplier<BlockRenderDispatcher>, Supplier<ItemRenderer>, Supplier<EntityRenderDispatcher>)->BlockEntityRenderDispatcher(Font, Supplier<EntityModelSet>, BlockRenderDispatcher, ItemModelResolver, ItemRenderer, EntityRenderDispatcher)renderItem已移除,在其特定类中实现
BlockEntityRendererProvider现在接受ItemModelResolvergetItemModelResolver- 获取返回物品模型的解析器。
ChestRenderer#xmasTextures- 返回是否应在箱子上渲染圣诞纹理。DecoratedPotRenderer现在有一个接受EntityModelSet的重载构造函数renderInHand- 渲染饰纹陶罐的物品模型。
ShulkerBoxRenderer现在有一个接受EntityModelSet的重载构造函数render- 渲染潜影盒。$ShulkerBoxModel#animate不再接受ShulkerBoxBlockEntity
SkullblockRenderer#createSkullRenderers->createModel,不是一对一
net.minecraft.client.renderer.entityEntityRenderDispatcher现在接受一个IteModelResolver、一个提供的EntityModelSet而不是实例,以及一个EquipmentAssetManager而不是EquipmentModelSetEntityRendererProvider$Context现在接受一个ItemModelResolver而不是ItemRenderer,以及一个EquipmentAssetManager而不是EquipmentModelSetgetItemRenderer->getItemModelResolver,不是一对一getEquipmentModels->getEquipmentAssets
FishingHookRenderer- 返回钓鱼钩的持有手臂。HumanoidMobRenderergetArmPose- 返回实体的手臂姿势。extractHumanoidRenderState现在接受一个ItemModelResolver
ItemEntityRenderergetSeedForItemStack已移除renderMultipleFromCount现在接受ItemClusterRenderState,并移除了ItemRenderer、ItemStack、BakedModel和 3d 布尔值
ItemRenderer不再实现ResourceManagerReloadListener- 构造函数现在只接受
ItemModelResolver render->renderItem,不是一对一renderBundleItem已移除getModel、resolveItemModel已移除
- 构造函数现在只接受
LivingEntityRenderer#itemRenderer->itemModelResolver,不是一对一OminousItemSpawnerRenderer现在使用ItemClusterRenderStateSkeletonRenderer#getArmPose->AbstractSkeletonRenderer#getArmPoseSnowGolemRenderer现在使用SnowGolemRenderState
net.minecraft.client.renderer.entity.layersCrossArmsItemLayer现在使用HoldingEntityRenderStateCustomHeadLayer不再接受ItemRendererDolphinCarryingItemLayer不再接受ItemRendererEquipmentLayerRenderer$TrimSpriteKey现在接受ResourceKey<EquipmentAsset>textureId- 获取纹饰的纹理 id。
FoxHeldItemLayer不再接受ItemRendererItemInHandLayer现在使用ArmedEntityRenderState- 构造函数不再接受
ItemRenderer renderArmWithItem不再接受BakedModel、ItemStack或ItemDisplayContext,而是接受ItemStackRenderState
- 构造函数不再接受
LivingEntityEmissiveLayer现在接受一个布尔值,确定该层是否始终可见PandaHoldsItemLayer不再接受ItemRendererPlayerItemInHandLayer不再接受ItemRendererrenderArmWithItem不再接受BakedModel、ItemStack或ItemDisplayContext,而是接受ItemStackRenderState
SnowGolemHeadLayer现在使用SnowGolemRenderStateWitchItemLayer不再接受ItemRenderer
net.minecraft.client.renderer.entity.player.PlayerRenderer#getArmPose现在是私有的net.minecraft.client.renderer.entity.stateArmedEntityRenderState- 一个用于在右手和左手持有物品的实体的渲染状态。HoldingEntityRenderState- 一个用于持有单个物品的实体的渲染状态。ItemClusterRenderState- 一个用于应多次渲染的物品的渲染状态。ItemDisplayEntityRenderState#itemRenderState、itemModel->item,不是一对一ItemEntityRenderState#itemModel、item->ItemClusterRenderState#item,不是一对一ItemFrameRenderState#itemStack、itemModel->item,不是一对一LivingEntityRenderStateheadItemModel、headItem->headItem,不是一对一- 手臂和手部方法已移至
ArmedEntityRenderState
OminousItemSpawnerRenderState->ItemClusterRenderStatePlayerRenderStatemainHandState、offHandState->ArmedEntityRenderState方法heldOnHead- 表示玩家头上的物品堆栈。
SkeletonRenderState#isHoldingBow- 表示骷髅是否在持弓。SnowGolemRenderState- 雪傀儡的渲染状态。ThrownItemRenderState#item、itemModel->item,不是一对一WitchRenderState#isHoldingPotion- 女巫是否在持药水。
net.minecraft.client.renderer.itemBlockModelWrapper- 包含模型及其关联染色的基本模型定义。BundleSelectedItemSpecialRenderer- 用于捆绑包选择的堆栈的特殊渲染器。ClampedItemPropertyFunction、ItemPropertyFunction-> 根据情况和属性,使用.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.conditionalBroken- 如果物品只剩下一点耐久。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.numericBundleFullness- 基于捆绑包内容的阈值。CompassAngle- 基于当前角度状态的阈值。CompassAngleState- 基于指南针当前朝向目标角度的阈值。Cooldown- 基于当前冷却百分比的阈值。Count- 基于堆栈数量的阈值。CrossbowPull- 基于弩被拉开的阈值。CustomModelDataProperty- 如果当前索引在DataComponents#CUSTOM_MODEL_DATA中设置了阈值。Damage- 基于剩余耐久百分比的阈值。NeedleDirectionHelper- 一个抽象类,帮助将指针指向正确的方向。RangeSelectItemModelProperties- 包含所有潜在的范围属性类型。RangeSelectItemModelProperty- 表示返回某个浮点数阈值的属性。Time- 基于当前时间的阈值。UseCycle- 基于正在使用的堆栈中归一化到某个周期模数的剩余时间的阈值。UseDuration- 基于正在使用的堆栈中剩余时间的阈值。
net.minecraft.client.renderer.item.properties.selectCharge- 基于弩的充能类型的情况。ContextDimension- 基于物品当前所在维度的情况。ContextEntityType- 基于持有实体类型的情况。CustomModelDataProperty- 如果当前索引在DataComponents#CUSTOM_MODEL_DATA中被设置为字符串。DisplayContext- 基于显示上下文的情况。ItemBlockState- 基于从持有方块状态属性的物品中获取属性值的情况。LocalTime- 基于简单日期格式模式的情况。MainHand- 基于持有物品的手臂的情况。SelectItemModelProperties- 包含所有潜在的选择情况属性类型。SelectItemModelProperty- 表示返回某种选择情况的属性。TrimMaterialProperty- 基于物品上纹饰材料的情况。
net.minecraft.client.renderer.specialBannerSpecialRenderer- 旗帜的物品渲染器。BedSpecialRenderer- 床的物品渲染器。ChestSpecialRenderer- 箱子的物品渲染器。ConduitSpecialRenderer- 潮涌核心的物品渲染器。DecoratedPotSpecialRenderer- 饰纹陶罐的物品渲染器。HangingSignSpecialRenderer- 悬挂式告示牌的物品渲染器。NoDataSpecialModelRenderer- 不需要从堆栈读取任何数据的物品渲染器。ShieldSpecialRenderer- 盾牌的物品渲染器。ShulkerBoxSpecialRenderer- 潜影盒的物品渲染器。SkullSpecialRenderer- 骷髅头的物品渲染器。SpecialModelRenderer- 表示从堆栈读取数据并渲染对象而不需要渲染状态的模型。SpecialModelRenderers- 包含所有潜在的特殊渲染器。StandingSignSpecialRenderer- 站立式告示牌的物品渲染器。TridentSpecialRenderer- 三叉戟的物品渲染器。
net.minecraft.client.resources.modelBakedModelisCustomRenderer已移除,被特殊渲染器系统取代overrides已移除,被属性渲染器系统取代
BlockStateModelLoader不再接受缺失模型definitionLocationToBlockMapper现在是私有的loadBlockStateDefinitionStack现在是私有的loadBlockStates- 获取方块状态的已加载模型。$LoadedBlockModelDefinition现在是包私有的$LoadedModel现在接受UnbakedBlockStateModel而不是UnbakedModel$LoadedModelsforResolving- 返回所有需要解析的模型。plainModels- 返回从模型位置到未烘焙模型的映射。
BuiltInModel类已移除ClientItemInfoLoader- 加载所有物品堆栈的所有模型。EquipmentModelSet->EquipmentAssetManagerItemModel->net.minecraft.client.renderer.item.ItemModelMissingBlockModel#MISSING现在是私有的ModelBakersprites- 返回获取精灵的获取器。rootName- 获取用于调试的模型名称。
ModelBakery(Map<ModelResourceLocation, UnbakedModel>, Map<ResourceLocation, UnbakedModel>, UnbakedModel)->ModelBakery(EntityModelSet, Map<ModelResourceLocation, UnbakedBlockStateModel>, Map<ResourceLocation, ClientItem>, Map<ResourceLocation, UnbakedModel>, UnbakedModel)bakeModels现在返回一个$BakingResultgetBakedTopLevelModels已移除$BakingResult- 包含所有已加载的模型。$TextureGetterget现在接受ModelDebugName而不是ModelResourceLocationreportingMissingReference- 处理当纹理未设置时如何报告。bind- 创建一个绑定到当前模型的独立获取器。
ModelDebugName- 返回用于调试的模型名称。ModelDiscoveryregisterStandardModels已移除registerSpecialModels- 添加系统加载的内部模型。addRoot- 添加一个可以解析的新模型。getUnreferencedModels- 返回已加载模型与已使用模型之间的差异。getTopModels已移除
ModelGroupCollector$GroupKey#create现在接受UnbakedBlockStateModel而不是UnbakedModelModelManagerspecialBlockModelRenderer- 返回特殊方块模型的渲染器。entityModels- 返回实体的模型集。getItemProeprties- 根据其资源位置返回客户端物品的属性。
ModelResourceLocation#inventory已移除ResolvableModel- 基础模型,通常是未烘焙的,具有需要解析的引用。SimpleBakedModel字段现在都是私有的bakeElements- 根据方块元素烘焙模型。$Builder不再有一个接受BlockModel的重载
SpecialModels类已移除SpriteGetter- 用于关联材质的图集精灵的获取器。UnbakedModel现在是一个ResolvableModelbake(ModelBaker, Function<Material, TextureAtlasSprite>, ModelState)->bake(TextureSlots, ModelBaker, ModelState, boolean, boolean, ItemTransforms)getAmbientOcclusion、getTopAmbientOcclusion- 返回是否应在物品上启用环境光遮蔽。getGuiLight、getTopGuiLight- 返回 GUI 内的光照面。getTransforms、getTopTransform、getTopTransforms- 返回基于显示上下文要应用的变换。getTextureSlots、getTopTextureSlots- 返回模型的纹理数据。getParent- 返回此模型的父模型。bakeWithTopModelValues- 烘焙模型。
net.minecraft.data.models.*->net.minecraft.client.data.models.*net.minecraft.world.itemBundleItem不再接受任何ResourceLocationopenFrontModel、openBackModel已移除
CrossbowItem$ChargeType- 弩正在充能的物品。DyeColor#getMixedColor- 返回最接近混合颜色的染料。Item$Properties#overrideModel已移除SpawnEggItem不再接受其染色颜色getColor已移除
net.minecraft.world.item.alchemy.PotionContentsgetColor(*)已移除getColorOr- 获取药水的自定义颜色,如果不存在则获取默认颜色。
net.minecraft.world.item.component.CustomModelData现在接受一个浮点数、标志、字符串和颜色的列表,用于根据提供的索引在自定义模型属性中使用net.minecraft.world.item.equipmentArmorMaterial现在接受ResourceKey<EquipmentAsset>而不是仅仅模型 idEquipmentAsset- 一个表示装备客户端信息键的标记EquipmentAssets- 所有原版装备资源。EquipmentModel->net.minecraft.client.resources.model.EquipmentClientInfoEquipmentModels->net.minecraft.client.data.models.EquipmentAssetProvider,不是一对一Equippable现在接受ResourceKey<EquipmentAsset>而不是仅仅模型 id$Builder#setModel->setAsset
net.minecraft.world.item.equipment.trimArmorTrim#getTexture已移除TrimMaterial不再接受物品模型索引,并且覆盖盔甲材料的键指向ResourceKey<EquipmentAsset>
net.minecraft.world.level.FoliageColorgetEvergreenColor->FOLIAGE_EVERGREENgetBirchColor->FOLIAGE_BIRCHgetDefaultColor->FOLIAGE_DEFAULTgetMangroveColor->FOLIAGE_MANGROVE
net.minecraft.world.level.block.RenderShape#ENTITYBLOCK_ANIMATED已移除net.minecraft.world.level.block.entityBannerBlockEntity#fromItem已移除BedBlockEntitty#setColor已移除BlockEntity#saveToItem已移除DecoratedPotBlockEntity#setFromItem、getPotAsItem已移除
net.minecraft.world.level.storage.loot.functions.SetCustomModelDataFunction现在接受一个浮点数、标志、字符串和颜色的列表,用于根据提供的索引在自定义模型属性中使用
生物 替换当前物品
与工具和盔甲分别是 DiggerItem 和 ArmorItem 子类型相关的最后一个硬编码实例已被重做:Mob#canReplaceCurrentItem。现在,它从 DataComponents#EQUIPPABLE 数据组件中读取堆栈的 EquipmentSlot。然后,根据情况使用不同的逻辑。
对于盔甲槽位,如果盔甲附有 EnchantmentEffectComponents#PREVENT_ARMOR_CHANGE 效果组件,则无法更换。否则,它将首先尝试比较盔甲属性,如果相等则比较盔甲韧性。
对于武器(通过手部槽位),它将首先检查生物是否有偏好的武器类型标签。如果有,它将把物品切换到标签中的武器,前提是标签中有一个物品而另一个没有。否则,它将尝试比较攻击伤害属性。
如果所有属性都相等,则它们都将默认采用以下逻辑。首先,它会尝试选择附魔最多的物品。然后,它会尝试选择剩余耐久度最多的物品(原始值,而不是百分比)。最后,它会检查其中一个物品是否通过 DataComponents#CUSTOM_NAME 具有自定义名称。
一个小问题是,
BambooSaplingBlock和BambooStalkBLock仍然硬编码检查主手物品是否为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.particleCherryParticle->FallingLeavesParticle,不是一对一,因为新类对其泛化有更大的配置ItemPickupParticle不再接受RenderBuffersParticle#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.textureHttpTexture->SkinTextureDownloader,不是一对一,因为新类只是一个返回要存储内容的工具MissingTextureAtlasSpritegetTexture->generateMissingImage,不是一对一getMissingImage(int, int)现在是公开的
SpriteLoader#loadAndStitch现在接受MetadataSectionType的集合而不是MetadataSectionSerializer
net.minecraft.client.resources.SkinManager不再接受TextureManagergetOrLoad现在返回一个Optional<PlayerSkin>的 future,而不仅仅是PlayerSkin
net.minecraft.client.resources.metadata.animationAnimationFrame现在是一个记录AnimationMetadataSection现在是一个记录AnimationMetadataSectionSerializer类已移除VillagerMetaDataSection->VillagerMetadataSectionVillagerMetadataSectionSerializer类已移除
net.minecraft.client.resources.metadata.textureTextureMetadataSection现在是一个记录TextureMetadataSectionSerializer类已移除
net.minecraft.server.packs.PackResources#getMetadataSection现在接受MetadataSectionType而不是MetadataSectionSerializernet.minecraft.server.packs.metadataMetadataSectionSerializer已移除,转而使用部分编解码器MetadataSectionType现在是一个记录,而不是MetadataSectionSerializer的扩展
net.minecraft.server.packs.resources.ResourceMetadatagetSection现在接受MetadataSectionType而不是MetadataSectionSerializercopySections现在接受MetadataSectionType的集合而不是MetadataSectionSerializer
音乐,现在带有音量控制
背景音乐现在通过 MusicInfo 类处理,它还存储音量以及关联的 Music。
net.minecraft.client.Minecraft#getSituationalMusic现在返回MusicInfo而不是Musicnet.minecraft.client.soundsMusicInfo- 一个记录,包含当前正在播放的Music及其音量。MusicManager#startPlaying现在接受MusicInfo而不是MusicSoundEngine#setVolume、SoundManager#setVolume- 设置关联声音实例的音量。
net.minecraft.world.level.biomeBiomegetBackgroundMusic现在返回一个可选的SimpleWeightedRandomList的音乐。getBackgroundMusicVolume- 获取背景音乐的音量。
BiomeSpecialEffects$Builder#silenceAllBackgroundMusic、backgroundMusic(SimpleWeightedRandomList<Music>)- 处理为生物群系设置背景音乐。
标签变更
minecraft:blocktall_flowers->bee_attractive
minecraft:itemtall_flowers、flowers已移除trim_templates已移除skeleton_preferred_weaponsdrowned_preferred_weaponspiglin_preferred_weaponspillager_preferred_weaponswither_skeleton_disliked_weapons
新增列表
com.mojang.blaze3d.platform.Window#isMinimized- 返回应用程序窗口是否最小化。com.mojang.blaze3d.vertex.VertexBufferuploadStatic- 通过使用带有STATIC_WRITEVertexBuffer的Tesselator的Consumer<VertexConsumer>立即上传提供的顶点数据。drawWithRenderType- 使用给定的RenderType将当前缓冲区绘制到屏幕。
com.mojang.math.MatrixUtil#isIdentity- 检查当前Matrix4f是否为单位矩阵。net.minecraftSuppressForbidden- 一个包含某些原因的注解,通常与需要 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.worldselectionExperimentsScreen$ScrollArea- 表示当前可用实验的一个可叙述滚动区域。SwitchGrid#layout- 返回要访问的网格布局。
net.minecraft.client.modelBannerFlagModel、BannerModel- 旗帜和悬挂式旗帜的模型。VillagerLikeModel#translateToArms- 平移姿势堆栈,使当前相对位置位于实体的手臂处。
net.minecraft.client.model.geom.EntityModelSet#vanilla- 创建一个包含所有原版模型的新模型集。net.minecraft.client.multiplayer.PlayerInfo#setShowHat、showHat- 处理在标签页覆盖层中显示玩家的帽子层。net.minecraft.client.renderer.blockentityAbstractSignRenderer- 告示牌如何作为方块实体渲染。HangingSignRenderercreateSignModel- 根据木材和附着位置创建一个告示牌模型。renderInHand- 在实体手中渲染模型。$AttachmentType- 一个枚举,根据其属性表示模型附着的位置。$ModelKey- 模型的键,结合了WoodType及其$AttachmentType。
SignRendererrenderInHand- 在实体手中渲染模型。
net.minecraft.client.renderer.entity.EntityRenderer#getShadowStrength- 返回显示阴影的原始不透明度。net.minecraft.client.renderer.entity.layers.CrossedArmsItemLayer#applyTranslation- 应用平移以在模型的手臂中渲染物品。net.minecraft.client.renderer.textureReloadableTexture- 可以从其关联内容重新加载的纹理。TextureContents- 包含与给定纹理关联的图像和元数据。TextureManagerregisterAndLoad- 使用给定名称注册一个可重新加载的纹理。registerForNextReload- 通过其资源位置注册一个纹理,以便在下一次重载时加载。
net.minecraft.commands.SharedSuggestionProvider#MATCH_SPLITTER- 定义一个匹配句点、下划线或正斜杠的匹配器。net.minecraft.core.BlockPos$TraversalNodeStatus- 一个标记,指示BlockPos是否应被使用、跳过或停止任何进一步的遍历。net.minecraft.core.component.PatchedDataComponentMaptoImmutableMap- 返回不可变的补丁或当前映射的副本。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#getShadowColor、withShadowColor- 处理组件阴影颜色的方法。net.minecraft.network.protocol.game.ServerboundPlayerLoadedPacket- 当客户端玩家加载到客户端世界时发送的数据包。net.minecraft.resources.FileToIdConverter#registry- 从注册表键获取文件转换器。net.minecraft.util.ExtraCodecsidResolverCodec- 创建一个将某个键映射到某个值的编解码器。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.entityLivingEntityresolvePlayerResponsibleForDamage- 获取对当前实体造成伤害的玩家。canBeNameTagged- 当为 true 时,实体可以用命名牌设置名称。
Mob#getPreferredWeaponType- 获取表示实体想要拾取的武器的标签。
net.minecraft.world.entity.ai.attributes.AttributeMap#resetBaseValue- 将属性实例重置为其默认值。net.minecraft.world.entity.monster.creakingCreakingactivate、deactivate- 处理嘎枝的大脑逻辑的激活。setTransient、isHeartBound、setHomePos、getHomePos- 处理家的位置。blameSourceForDamage- 找到对伤害负责的玩家。tearDown- 处理嘎枝被摧毁时的情况。creakingDeathEffects- 处理嘎枝的死亡。playerIsStuckInYou- 检查是否有至少四个玩家卡在嘎枝中。setTearingDown、isTearingDown- 处理拆除状态。hasGlowingEyes、checkEyeBlink- 处理眼睛状态。
net.minecraft.world.entity.player.PlayerhasClientLoaded、setClientLoaded- 客户端玩家是否已加载。tickClientLoadTimeout- Tick计时器,用于在客户端玩家未加载时等待多长时间后将其踢出。
net.minecraft.world.itemItem#shouldPrintOpWarning- 是否应根据存储的方块实体数据和管理员权限向玩家打印警告。ItemStackgetCustomName- 返回物品的自定义名称,如果不存在组件则返回null。immutableComponents- 返回不可变的补丁或堆栈组件映射的副本。hasNonDefault- 返回数据组件是否有自定义值而不是仅仅默认值。
net.minecraft.world.item.component.CustomDataparseEntityId- 从组件中读取实体 id。parseEntityType- 从 id 中读取实体类型,并将其映射到其注册表对象。
net.minecraft.world.item.crafting.Ingredient#isEmpty- 返回原料是否没有值。net.minecraft.world.item.trading.Merchant#stillValid- 检查玩家是否仍然可以访问该商人。net.minecraft.world.levelLevel#dragonParts- 返回作为末影龙部件的实体列表。ServerExplosion#getDamageSource- 返回爆炸的伤害来源。
net.minecraft.world.level.blockEyeblossomBlock$Typeblock- 获取当前类型的方块。state- 获取当前类型的方块状态。transform- 返回此类型的相反状态。
FlowerBlock#getBeeInteractionEffect- 返回蜜蜂与花互动时获得的效果。FlowerPotBlock#opposite- 返回方块的反向状态,仅适用于花盆中的 eyeblossom。MultifaceBlock#canAttachTo- 返回此方块是否可以附着到另一个方块。MultifaceSpreadeableBlock- 一个可以自然蔓延的多面方块。
net.minecraft.world.level.block.entity.trialspawnerTrialSpawner#overrideEntityToSpawn- 更改要在试炼中生成的实体。TrialSpawnerConfig#withSpawning- 设置在试炼中生成的实体。
变更列表
com.mojang.blaze3d.platform.NativeImage#upload不再接受三个设置TEXTURE_2D的过滤模式或纹理包裹钳位的布尔值- 这已移至
AbstractTexture#setClamp和#setFilter
- 这已移至
net.minecraft.client.guiGui#clear->clearTitlesGuiGraphics#drawWordWrap有一个新的重载,接受是否应对文本应用阴影- 默认版本启用阴影而不是禁用它
net.minecraft.client.gui.componentsAbstractContainerWidget现在实现AbstractScrollAreaAbstractScrollWidget-> 根据用例使用AbstractScrollArea或AbstractTextAreaWidget,不是一对一AbstractSelectionListsetRenderHeader现在被捆绑到一个带有额外整数的新构造函数中getMaxScroll->AbstractScrollArea#maxScrollAmountgetScrollAmount->AbstractScrollArea#scrollAmountscrollbarVisible->AbstractScrollArea#scrollbarVisiblesetClampedScrollAmount、setScrollAmount->AbstractScrollArea#setScrollAmountclampScrollAmount->refreshScrollAmountupdateScrollingState->AbstractScrollArea#updateScrollinggetScrollbarPosition、getDefaultScrollbarPosition->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.screensLoadingOverlay#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.modelDonkeyModel#createBodyLayer、createBabyLayer现在接受一个缩放因子VillagerHeadModel->VillagerLikeModel
net.minecraft.client.model.geom.EntityModelSet不再是ResourceManagerReloadListenernet.minecraft.client.multiplayer.MultiPlayerGameMode#handlePickItem->handlePickItemFromBlock或handlePickItemFromEntity,同时提供要同步的实际对象数据和一个关于是否包含被拾取对象数据的booleannet.minecraft.client.particle.CherryParticle->FallingLeavesParticle,不是一对一,因为新类对其泛化有更大的配置net.minecraft.client.player.ClientInput#tick不再接受任何参数net.minecraft.client.rendererCubeMap#preload->registerTextures,不是一对一LevelRendererrenderLevel不再接受LightTextureonChunkLoaded->onChunkReadyToRender
PostChainConfig$Pass#program->programIdprogram现在返回具有给定programId的ShaderProgram
ScreenEffectRenderer#renderScreenEffect现在接受一个MultiBufferSourceSectionOcclusionGraph#onChunkLoaded->onChunkReadyToRenderSheets#createSignMaterial、createHangingSignMaterial现在有一个接受ResourceLocation的重载SkyRendererrenderSunMoonAndStars、renderSunriseAndSunset现在接受一个MultiBufferSource$BufferSource而不是TesselatorrenderEndSky不再接受PoseStack
WeatherEffectRenderer#render现在接受一个MultiBufferSource$BufferSource而不是LightTexture
net.minecraft.client.renderer.blockentityBannerRenderer#createBodyLayer->BannerModel#createBodyLayer,不是一对一HangingSignRenderercreateHangingSignLayer现在接受一个HangingSignRenderer$AttachmentType$HangingSignModel现在被Model$Simple取代,尽管其字段可以从根获取
SkullBlockRenderer#getRenderType现在有一个接受ResourceLocation的重载,用于覆盖表示玩家纹理
net.minecraft.client.renderer.entity.AbstractHorseRenderer、DonkeyRenderer不再接受浮点缩放net.minecraft.client.renderer.entity.layers.CrossedArmsItemLayer现在要求泛型M是VillagerLikeModelnet.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.networkNoOpFrameEncoder被LocalFrameEncoder取代,不是一对一NoOpFrameDecoder被LocalFrameDecoder取代,不是一对一MonitorFrameDecoder被MonitoredLocalFrameDecoder取代,不是一对一
net.minecraft.network.protocol.gameClientboundLevelParticlesPacket现在接受一个布尔值,确定粒子是否应始终渲染ClientboundMoveVehiclePacket现在是一个记录ClientboundPlayerInfoUpdatePacket$Entry现在接受一个布尔值,表示是否应显示帽子ClientboundSetHeldSlotPacket现在是一个记录ServerboundMoveVehiclePacket现在是一个记录ServerboundPickItemPacket->ServerboundPickItemFromBlockPacket、ServerboundPickItemFromEntityPacket;不是一对一
- `net.minecraft.server.level
ServerLevel#sendParticles现在有一个接受覆盖限制距离和粒子是否应始终显示的重载- 其他接受覆盖限制器的重载现在也接受粒子是否应始终显示的布尔值
ServerPlayer#doCheckFallDamage->Entity#doCheckFallDamage,现在是 final
net.minecraft.utilARGB#from8BitChannel现在是私有的,单个浮点分量可以通过alphaFloat、redFloat、greenFloat和blueFloat获得SpawnUtil#trySpawnMob现在接受一个布尔值,当为 false 时,允许实体无论与周围区域的碰撞状态如何都可以生成
net.minecraft.util.profiling.jfr.callback.ProfiledDuration#finish现在接受一个布尔值,表示分析的事件是否成功net.minecraft.util.profiling.jfr.parse.JfrStatsResults现在接受一个结构生成统计信息的列表net.minecraft.world.effect.PoisonMobEffect、WitherMobEffect现在是公开的net.minecraft.world.entityEntitysetOnGroundWithMovement有一个重载,将水平碰撞设置为实体当前状态的任何值。awardKillScore不再接受整数makeBoundingBox()现在是 finalmakeBoundingBox(Vec3)现在
onlyOpCanSetNbt->EntityType#onlyOpCanSetNbt
LeashablereadLeashData现在是私有的,被一个不返回任何内容的方法取代dropLeash(boolean, boolean)->dropLeash()、removeLeash、onLeashRemoved;不是一对一,因为它们都在内部调用私有的dropLeash
LivingEntityisLookingAtMe不再接受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#getProgressAabb、getProgressDeltaAabb现在接受一个移动Vec3net.minecraft.world.entity.playerInventorysetPickedItem->addAndPickItemfindSlotMatchingCraftingIngredient现在接受一个ItemStack进行比较
Player#getPermissionLevel现在是公开的StackedContents$IngredientInfo现在是一个接口,像一个接受某些物品的谓词
net.minecraft.world.entity.projectile.FishingHook不再接受ItemStacknet.minecraft.world.inventory.Slot#getNoItemIcon现在返回单个ResourceLocation而不是一对net.minecraft.world.itemItem$TooltipContext#of现在接受查看物品的PlayerMobBucketItem现在需要一个Mob实体类型 -SpawnEggItem#spawnsEntity、getType现在接受一个HolderLookup$Provider
net.minecraft.world.item.craftingIngredient现在实现StackedContents$IngredientInfo<Holder<Item>>items现在返回一个流而不是一个列表
PlacementInfo#slotInfo->slotsToIngredientIndex,不是一对一
net.minecraft.world.level.Level#addParticle现在接受一个布尔值,表示粒子是否应始终显示net.minecraft.world.level.blockBlock#getCloneItemStack->state.BlockBehaviour#getCloneItemStack,现在是 protectedCherryLeavesBlock->ParticleLeavesBlockCreakingHeartBlock#canSummonCreaking->isNaturalNightMultifaceBlock不再是抽象的,并且实现SimpleWaterloggedBlockgetSpreader->MultifaceSpreadeableBlock#getSpreader
SculkVeinBlock现在是MultifaceSpreadeableBlock的一个实例SnowyDirtBlock#isSnowySetting现在是 protected
net.minecraft.world.level.block.entityAbstractFurnaceBlockEntitylitTime->litTimeRemaininglitDuration->litTotalTimecookingProgress->cookingTimer
BeehiveBlockEntity#addOccupant现在接受一个Bee而不是EntityCreakingHeartBlockEntity#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.configurationsMultifaceGrowthConfiguration现在接受MultifaceSpreadableBlock而不是MultifaceBlockSimpleBlockConfiguration现在接受一个布尔值,表示是否安排Tick更新
net.minecraft.world.level.levelgen.structure.Structure#generate现在接受Structure持有者和Level资源键,仅用于分析
移除列表
com.mojang.blaze3d.systems.RenderSystem#overlayBlendFuncnet.minecraft.client.gui.components.AbstractSelectionListclickedHeaderisValidMouseClick
net.minecraft.client.gui.screens.recipebook.RecipeCollection#hasSingleResultItemnet.minecraft.client.modelDrownedModel#getArmPose,现在是ArmedEntityRenderState的一部分FelineModel#CAT_TRANSFORMERHumanoidModel#getArmPose,现在是ArmedEntityRenderState的一部分PlayerModel#getArmPose,现在是ArmedEntityRenderState的一部分SkeletonModel#getArmPose,现在是ArmedEntityRenderState的一部分VillagerModel#BABY_TRANSFORMER
net.minecraft.client.renderer.textureAbstractTextureloadresetgetDefaultBlur
PreloadedTextureTextureManagergetTexture(ResourceLocation, AbstractTexture)register(String, DynamicTexture)preload
net.minecraft.server.level.TicketType#POST_TELEPORTnet.minecraft.world.entity.LivingEntity#deathScorenet.minecraft.world.entity.ai.navigation.FlyingPathNavigation、GroundPathNavigationcanPassDoors、setCanPassDoorscanOpenDoors
net.minecraft.world.entity.monster.creaking.CreakingTransientnet.minecraft.world.entity.player.StackedItemContents#convertIngredientContentsnet.minecraft.world.itemCompassItem#getSpawnPositionItemStack#clearComponents
net.minecraft.world.item.crafting.PlacementInfoingredientToContentsunpackedIngredients$SlotInfo
net.minecraft.world.level.block.CreakingHeartBlock$CreakingHeartStatenet.minecraft.world.level.block.entity.BlockEntity#onlyOpCanSetNbtnet.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#preRemoveSideEffects 和 BlockBehaviour#affectNeighborsAfterRemoval。
BlockEntity#preRemoveSideEffects 现在负责在方块实体从等级中移除之前从中移除任何东西。默认情况下,如果 BlockEntity 是一个 Container 实例,它会将容器的内容丢弃到等级中。其他逻辑可以在这里处理,但它通常应避免移除 BlockEntity 本身,除非方块实体的位置倾向于动态变化,例如活塞。
然后,LevelChunk 逻辑将在调用 BlockBehaviour#affectNeighborsAfterRemoval 之前调用 removeBlockEntity。这应该只向其他方块发送更新,指示此方块已从等级中移除。对于 BlockEntity 持有者,可以通过调用 Containers#updateNeighboursAfterDestroy 轻松完成。否则,可能希望根据情况自己调用 Level#updateNeighborsAt。
net.minecraft.world.ContainersupdateNeighboursAfterDestroy- 在销毁指定位置的方块后更新邻居状态。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。结果要么存储在某个键到 VoxelShape 的 Map 中,要么在使用 Block#getShapeForEachState 时存储为 Function<BlockState, VoxelShape>。
大多数之前有公开或受保护 VoxelShape 的 Block 子类现在都是私有的,重命名为通常称为 SHAPE 或 SHAPES 的字段。存储的 VoxelShape 也可能在 Function 中,而不是直接存储映射本身。
com.mojang.math.OctahedralGrouppermute- 返回给定轴在指定组内被置换到的轴。fromAngles- 使用提供的 X 和 Y 旋转创建一个组。
net.minecraft.core.Direction$Axis#choose现在有一个接受三个布尔值的重载net.minecraft.world.level.block.Blockboxes- 创建比指定数量多一个的盒子,使用索引作为创建VoxelShape的函数的一部分。cube- 创建一个指定大小的居中立方体。column- 创建一个指定大小的水平居中柱体。boxZ- 创建一个指定大小的垂直居中(围绕 X 轴)的立方体/柱体。getShapeForEachState现在返回一个包装ImmutableMap的Function,还有一个方法只考虑指定的属性而不是所有可能的状态。
net.minecraft.world.phys.shapesDiscreteVoxelShape#rotate- 根据OctahedralGroup的置换旋转体素形状。ShapesblockOccudes->blockOccludesrotate- 根据OctahedralGroup的置换围绕提供的向量(如果未指定则围绕方块中心)旋转给定的体素形状。equal- 检查两个体素形状是否等效。rotateHorizontalAxis- 创建一个轴到VoxelShape的映射,表示围绕 Y 轴旋转的方块。rotateAllAxis- 创建一个轴到VoxelShape的映射,表示围绕任何轴旋转的方块。rotateHorizontal- 创建一个方向到VoxelShape的映射,表示围绕 Y 轴旋转的方块。rotateAll- 创建一个方向到VoxelShape的映射,表示围绕任何轴旋转的方块。rotateAttachFace- 创建一个面到方向到VoxelShape的映射,表示当附着在其他方块面上时围绕 Y 轴旋转的方块。
VoxelShape#move现在有一个接受Vec3i的重载
武器、工具和盔甲:去除冗余
武器、工具和盔甲有很多更新,分别移除了对 SwordItem、DiggerItem 和 ArmorItem 硬编码基类的依赖。这些已被其关联的数据组件取代:WEAPON 用于伤害,TOOL 用于挖掘,ARMOR 用于保护,BLOCKS_ATTACKS 用于盾牌。此外,缺失的属性通常通过设置 ATTRIBUTE_MODIFIERS、MAX_DAMAGE、MAX_STACK_SIZE、DAMAGE、REPAIRABLE 和 ENCHANTABLE 来指定。鉴于几乎所有非特定逻辑都已移至数据组件,这些类现在已被完全移除。使用可用的物品属性方法之一或直接调用 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.DataComponentsUNBREAKABLE现在是一个Unit实例HIDE_ADDITIONAL_TOOLTIP、HIDE_TOOLTIP已被整合到TOOLTIP_DISPLAY中,接受一个TooltipDisplayBLOCKS_ATTACKS- 一个组件,决定持有的物品是否可以阻挡来自某些伤害源的攻击INSTRUMENT现在接受一个InstrumentComponentPROVIDES_TRIM_MATERIAL、PROVIDES_BANNER_PATTERNS处理其关联类型的提供者。BEES现在接受一个Bees组件BREAK_SOUND- 物品损坏时播放的声音。
net.minecraft.data.recipesRecipeProvider#trimSmithing现在接受TrimPattern的键SmithingTrimRecipeBuilder现在接受TrimPattern的持有者
net.minecraft.world.entity.LivingEntityblockUsingShield->blockUsingItemblockedByShield->blockedByItemhurtCurrentlyUsedShield已移除canDisableBlocking->getSecondsToDisableBlocking,不是一对一applyItemBlocking- 应用用物品格挡攻击时所做的伤害减少。isDamageSourceBlocked已移除
net.minecraft.world.entity.player.Player#disableShield->net.minecraft.world.item.component.BlocksAttacks#disablenet.minecraft.world.itemAnimalArmorItem类已移除ArmorItem类已移除AxeItem现在继承ItemBannerPatternItem类已移除DiggerItem类已移除FireworkStarItem类已移除HoeItem现在继承ItemInstrumentItem不再接受标签键ItemgetBreakingSound已移除$Propertiestool- 将物品设置为工具。pickaxe- 将物品设置为镐。sword- 将物品设置为剑。axe- 将物品设置为斧。hoe- 将物品设置为锄。shovel- 将物品设置为锹。trimMaterial- 将物品设置为提供纹饰材料。
ItemStack#getBreakingSound已移除PickaxeItem类已移除ShovelItem现在继承ItemSwordItem类已移除ToolMaterial#applyToolProperties现在接受一个布尔值,表示武器是否可以禁用格挡器(例如盾牌)
net.minecraft.world.item.componentBees- 一个包含蜂巢居住者的组件。BlocksAttacks- 用于用持有的物品格挡攻击的组件。InstrumentComponent- 一个包含乐器播放声音的组件。ProvidesTrimMaterial- 一个为某些盔甲提供要使用的纹饰材料的组件。Tool现在接受一个布尔值,表示该工具是否可以在创造模式下破坏方块Unbreakable类已移除Weapon- 一个数据组件,包含物品可以造成多少伤害以及它禁用格挡器(例如盾牌)的时间。
net.minecraft.world.item.equipmentAllowedEntitiesProvider- 一个函数式接口,用于获取允许处理关联逻辑的实体。ArmorMaterialhumanoidProperties->Item$Properties#humanoidArmoranimalProperties->Item$Properties#wolfArmor、horseArmorcreateAttributes现在是公开的
EquippableequipOnInteract- 当为 true 时,该物品可以在与另一个实体交互时装备到该实体上。saddle- 为马鞍创建一个可装备。equipOnTarget- 将物品装备到目标实体上。
推断马鞍:装备变更
为马鞍添加了一个新的 EquipmentSlot,这带来了用于泛化槽位逻辑的新变化。
首先,现在可以通过一个称为 SimpleEquipmentLayer 的附加 RenderLayer 来处理实体的装备槽位渲染。这接受实体渲染器、EquipmentLayerRenderer、要渲染的层类型、从实体状态获取 ItemStack 的函数,以及成年和幼年模型。渲染器将尝试从关联的可装备数据组件中查找客户端信息,并使用该信息在必要时渲染层。
接下来,实体上不再为每个装备槽位设置单独的列表,而是有一个通用的 EntityEquipment 对象,它持有一个槽位到 ItemStack 的映射委托。这大大简化了存储逻辑。
最后,可装备现在可以通过设置 equipOnInteract 来指定物品是否应在交互时(通常是右键单击)装备到生物上。
net.minecraft.client.modelCamelModelhead现在是公开的createBodyMesh- 创建骆驼的网格定义。
CamelSaddleModel- 带有马鞍的骆驼模型。DonkeyModel#createSaddleLayer- 为带有马鞍的驴创建层定义。EquineSaddleModel- 带有马鞍的马科动物的模型。PolarBearModel#createBodyLayer现在接受一个布尔值,表示实体是否为幼年
net.minecraft.client.renderer.entity.layers.HorseArmorLayer、SaddleLayer->SimpleEquipmentLayernet.minecraft.client.renderer.entity.stateCamelRenderState#isSaddled->saddle,不是一对一EquineRenderState#isSaddled->saddle,不是一对一PigRenderState#isSaddled->saddle,不是一对一SaddleableRenderState类已移除StriderRenderState#isSaddled->saddle,不是一对一CamelRenderState#isSaddled->saddle,不是一对一
net.minecraft.client.resources.model.EquipmentClientInfo$LayerType现在包含:PIG_SADDLESTRIDER_SADDLECAMEL_SADDLEHORSE_SADDLEDONKEY_SADDLEMULE_SADDLEZOMBIE_HORSE_SADDLESKELETON_HORSE_SADDLEtrimAssetPrefix- 返回应用于包含关联类型的盔甲纹饰的纹理的前缀。
net.minecraft.world.entityEntityEquipment- 一个槽位到物品堆栈的映射,表示实体的装备。EquipmentSlotSADDLE、$Type#SADDLEcanIncreaseExperience- 该槽位是否可以在杀死生物时增加获得的经验值数量。
EquipmentSlotGroup现在是一个可迭代对象SADDLEslots- 返回组内的槽位。
LivingEntitygetEquipSound- 获取将物品装备到槽位时要播放的声音。getArmorSlots、getHandSlots、getArmorAndBodyArmorSlots、getAllSlots已移除equipment- 实体穿戴的装备。createEquipment- 设置实体穿戴的默认装备。drop- 丢弃指定的堆栈。getItemBySlot、setItemBySlot不再是抽象的。verfiyEquippedItem已移除
MobisSaddled- 检查马鞍槽位中是否有物品。createEquipmentSlotContainer- 为装备槽位创建一个单物品容器。
OwnableEntity#getRootOwner- 获取实体的最高级所有者。Saddleable接口已移除
net.minecraft.world.entity.animal.horse.AbstractHorsesyncSaddletoClients已移除getBodyArmorAccess已移除
net.minecraft.world.entity.playerInventoryarmor、offhand->EQUIPMENT_SLOT_MAPPING,不是一对一selected现在是私有的setSelectedHotbarSlot->setSelectedSlot- 还存在获取器
getSelectedSlot
- 还存在获取器
getSelected->getSelectedItem- 还存在设置器
setSelectedItem
- 还存在设置器
getNonEquipmentItems- 返回库存中的非装备物品列表。getDestroySpeed已移除getArmor已移除
PlayerEquipment- 玩家穿戴的装备。
net.minecraft.world.itemItem#inventoryTick(ItemStack, Level, Entity, int, boolean)->inventoryTick(ItemStack, ServerLevel, Entity, EquipmentSlot)SaddleItem类已移除
加权列表重做
加权随机列表已被重新设计为一个基本类,用于保存加权条目,以及一个辅助类,可以从对象本身获取权重。
首先是 WeightedList。它实际上是 SimpleWeightedRandomList 的替代品,通过将 Weighted(WeightedEntry 的替代品)条目存储在列表本身中,以完全相同的方式工作。在内部,列表要么存储为对象条目的扁平数组,要么在总权重大于 64 时存储为紧凑加权列表。然后,要获取一个随机元素,可以调用 getRandom 或 getRandomOrThrow 来获取一个条目。如果列表中没有元素,这两个方法都将返回某种形式的空对象或异常。
然后是 WeightedRandom 中的静态辅助方法。这些方法接受原始列表和某个 ToIntFunction,该函数从列表的对象中获取权重。一些方法还接受一个整数,表示要选择的最大索引或与加权索引关联的条目。
net.minecraft.client.resources.model.WeightedBakedModel现在接受WeightedList而不是SimpleWeightedRandomListnet.minecraft.util.randomSimpleWeightedRandomList、WeightedRandomList->WeightedList,现在是 final,不是一对一contains- 检查列表是否包含此元素。
Weight类已移除WeightedEntry->Weighted- 所有
WeightedRandom静态方法现在接受一个ToIntFunction来获取提供的列表中某个条目的权重
net.minecraft.util.valueproviders.WeightedListInt现在接受WeightedListnet.minecraft.world.level.SpawnData#LIST_CODEC现在是一个WeightedList的SpawnDatanet.minecraft.world.level.biomeBiome#getBackgroundMusic现在是一个WeightedList的MusicBiomeSpecialEffects#getBackgroundMusic、$Builder#backgroundMusic现在是一个WeightedList的MusicMobSpawnSettings#EMPTY_MOB_LIST、getMobs现在是一个WeightedList
net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig#spawnPotentialsDefinition、lootTablesToEject现在接受WeightedListnet.minecraft.world.level.chunk.ChunkGenerator#getMobsAt现在返回一个WeightedListnet.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider现在使用WeightedListnet.minecraft.world.level.levelgen.heightproviders.WeightedListHeight现在使用WeightedListnet.minecraft.world.level.levelgen.structure.StructureSpawnOverride现在接受WeightedListnet.minecraft.world.level.levelgen.structure.pools.aliasPoolAliasBinding#random、randomGroup现在接受WeightedListRandom现在接受WeightedListRandomGroup现在接受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.levelChunkMap现在接受TicketStorage$TrackedEntity#broadcastIgnorePlayers- 将数据包广播给所有玩家,但 UUID 列表中的玩家除外。
DistanceManagerchunksToUpdateFutures现在是 protected,并接受一个TicketStoragepurgeStaleTickets->net.minecraft.world.level.TicketStorage#purgeStaleTicketsgetTicketDebugString->net.minecraft.world.level.TicketStorage#getTicketDebugStringgetChunkLevel- 返回当前区块等级,或当提供的布尔值为 true 时返回模拟等级。getTickingChunks已移除removeTicketsOnClosing已移除$ChunkTicketTracker->LoadingChunkTracker或SimulationChunkTracker
ServerChunkCacheaddRegionTicket->addTicketWithRadius或addTicketremoveRegionTicket->removeTicketWithRadiusremoveTicketsOnClosing->deactivateTicketsOnClosing
Ticket不再是 final,也不再实现Comparable- 构造函数不再接受键
CODECsetCreatedTick、timedOut->resetTicksLeft、decreaseTicksLeft、isTimedOut;不是一对一
TicketType现在是一个记录,不再有泛型getComparator已移除doesLoad、doesSimulate- 检查加载票用途是否用于其特定实例。$TicketUse- 加载票可以用于什么。
TickingTracker->SimulationChunkTracker
net.minecraft.world.level.ForcedChunksSavedData->TicketStoragenet.minecraft.world.level.chunk.ChunkSourceupdateChunkForced现在返回一个布尔值,指示区块是否已被强制加载getForceLoadedChunks- 返回所有已被强制加载的区块。
游戏测试大修
游戏测试已被完全改造为一个基于注册表的系统,与之前自动注解驱动的系统完全不同。然而,使用该系统所需的大多数实现必须由您自己完成,而不是由原版提供。因此,此说明将涵盖整个系统,包括哪些部分需要大量工作才能使其类似于先前版本的注解驱动系统。
环境
所有游戏测试都在某个环境中发生。大多数情况下,测试可以独立于区域进行,但有时环境需要以某种方式进行管理,例如检查实体或方块在给定时间是否执行了某些操作。为了促进给定测试实例的环境设置和拆除,创建了一个 TestEnvironmentDefinition。
TestEnvironmentDefinition 的工作方式类似于 BeforeBatch 和 AfterBatch 注解。环境包含两个方法 setup 和 teardown,用于管理测试的 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.blockentityBeaconRenderer现在有一个泛型,接受BlockEntity和BeaconBeamOwner的子类型StructureBlockRenderer->BlockEntityWithBoundingBoxRenderer,不是一对一
net.minecraft.core.registries.Registries#TEST_FUNCTION、TEST_ENVIRONMENT_DEFINITION_TYPE、TEST_INSTANCE_TYPEnet.minecraft.gametest.Main- 游戏测试服务器的入口点。net.minecraft.gametest.frameworkAfterBatch、BeforeBatch注解已移除BlockBasedTestInstance- 用于测试测试方块的测试实例。BuiltinTestFunctions- 包含所有已注册的测试函数。FailedTestTracker- 用于保存所有失败的测试的对象。FunctionGameTestInstance- 用于运行测试函数的测试实例。GameTest注解已移除GameTestAssertException现在继承GameTestExceptionGameTestException- 游戏测试执行期间抛出的异常。GameTestBatch现在接受索引和环境定义,而不是名称和批次设置GameTestBatchFactoryfromTestFunction->divideIntoBatches,不是一对一toGameTestInfo已移除toGameTestBatch现在接受环境定义和索引$TestDecorator- 从测试实例和等级创建测试信息列表。
GameTestEnvironments- 包含用于批处理游戏测试实例的所有环境。GameTestGenerator注解已移除GameTestHelpertickBlock- 在特定位置Tick方块。assertionException- 返回一个在出错时要抛出的新异常。getBlockEntity现在接受一个Class来将方块实体转换为assertBlockTag- 检查该位置的方块是否在提供的标签内。assertBlock现在接受一个方块 -> 组件函数,用于错误消息。assertBlockProperty现在接受Component而不是字符串assertBlockState现在接受什么都不接受、一个方块状态 -> 组件函数或一个提供的组件assertRedstoneSignal现在接受一个提供的组件assertContainerSingle- 断言容器恰好包含一个指定物品。assertEntityPosition、assertEntityProperty现在接受一个组件fail现在接受一个Component作为错误消息assertTrue、assertValueEqual、assertFalse现在接受一个组件
GameTestInfo现在接受一个持有者包装的GameTestInstance而不是TestFunctionsetStructureBlockPos->setTestBlockPosplaceStructure现在不返回任何内容getTestName-id,不是一对一getStructureBlockPos->getTestBlockPosgetStructureBlockEntity->getTestInstanceBlockEntitygetStructureName->getStructuregetTestFunction->getTest、getTestHolder,不是一对一getOrCalculateNorthwestCorner、setNorthwestCorner已移除fail现在接受Component或GameTestException而不是ThrowablegetError现在返回GameTestException而不是Throwable
GameTestInstance- 定义要运行的测试。GameTestInstances- 包含所有已注册的测试。GameTestMainUtil- 用于运行游戏测试服务器的工具。GameTestRegistry类已移除GameTestSequencetickAndContinue、tickAndFailIfNotComplete现在接受一个整数作为刻,而不是 longthenFail现在接受一个提供的GameTestException而不是Throwable
GameTestServer#create现在接受一个可选的字符串和布尔值,而不是测试函数集合和起始位置GeneratedTest- 一个包含要在给定环境下运行的测试和要应用的函数的对象GameTestTicker$State- 一个枚举,包含游戏测试Tick器当前正在执行的状态。GameTestTimeoutException现在继承GameTestExceptionReportGameListener#spawnBeacon已移除StructureBlockPosFinder->TestPosFinderStructureUtilstestStructuresDir现在是一个路径getStructureBounds、getStructureBoundingBox、getStructureOrigin、addCommandBlockAndButtonToStartTest已移除createNewEmptyStructureBlock->createNewEmptyTest,不是一对一getStartCorner、prepareTestStructure、encaseStructure、removeBarriers已移除findStructureBlockContainingPos->findTestContainingPosfindNearestStructureBlock->findNearestTestfindStructureByTestFunction、createStructureBlock已移除findStructureBlocks->findTestBlockslookedAtStructureBlockPos->lookedAtTestPos
TestClassNameArgument已移除TestEnvironmentDefinition- 定义测试运行的环境,通过在等级上适当设置数据。TestFinder不再包含上下文的泛型$Builder#allTests、allTestsInClass、locateByName已移除$Builder#byArgument->byResourceSelection
TestFunction->TestData,不是一对一TestFunctionArgument->net.minecraft.commands.arguments.ResourceSelectorArgumentTestFunctionFinder->TestInstanceFinderTestFunctionLoader- 保存要加载和运行的测试函数列表。UnknownGameTestException- 当游戏测试的错误未知时抛出的异常。
net.minecraft.network.protocol.gameClientboundTestInstanceBlockState- 发送到客户端的数据包,包含测试的状态及其大小。ServerboundSetTestBlockPacket- 发送到服务器的数据包,用于设置测试方块中要运行的信息。ServerboundTestInstanceBlockActionPacket- 发送到服务器的数据包,用于在测试方块中设置测试实例。
net.minecraft.world.entity.player.PlayeropenTestBlock- 打开一个测试方块。openTestInstanceBlock- 为游戏测试实例打开一个测试方块。
net.minecraft.world.level.blockTestBlock- 用于运行游戏测试的方块。TestInstanceBlock- 用于管理单个游戏测试的方块。
net.minecraft.world.level.block.entityBeaconBeamOwner- 一个接口,表示具有信标光束的方块实体。BeaconBlockEntity现在实现BeaconBeamOwnerBeaconBeamSection->BeaconBeamOwner$Section
BoundingBoxRenderable- 一个接口,表示可以渲染任意大小边界框的方块实体。StructureBlockEntity现在实现BoundingBoxRenderableTestBlockEntity- 用于运行游戏测试的方块实体。TestInstanceBlockEntity- 用于管理单个游戏测试的方块实体。
net.minecraft.world.level.block.state.properties.TestBlockMode- 一个用于表示与测试方块关联的游戏测试当前状态的属性。
数据组件获取器
数据组件系统现在可以通过使用 DataComponentGetter 在任意对象上表示。顾名思义,获取器负责从关联的类型键获取组件。方块实体和实体都使用 DataComponentGetter 来允许查询内部数据,例如变体信息或自定义名称。它们都有从另一个持有者收集数据组件的方法(通过 applyImplicitComponents 或 applyImplicitComponent)。方块实体还包含通过 collectImplicitComponents 收集到另一个持有者的方法。
物品
ItemSubPredicate 已被完全替换为 DataComponentPredicate。每个子谓词在系统中都有其适当的对应项。
net.minecraft.advancements.critereon.*->net.minecraft.core.component.predicates.*ItemAttributeModifiersPredicate->AttributeModifiersPredicateItemBundlePredicate->BundlePredicateItemContainerPredicate->ContainerPredicateItemCustomDataPredicate->CustomDataPredicateItemDamagePredicate->DamagePredicateItemEnchantmentsPredicate->EnchantmentsPredicateItemFireworkExplosionPredicate->FireworkExplosionPredicateItemFireworksPredicate->FireworksPredicateItemJukeboxPlayablePredicate->JukeboxPlayablePredicateItemPotionsPredicate->PotionsPredicateItemSubPredicate->DataComponentPredicate,不是一对一SINGLE_STREAM_CODEC
ItemSubPredicates->DataComponentPredicates,不是一对一ItemTrimPredicate->TrimPredicateItemWritableBookPredicate->WritableBookPredicateItemWrittenBookPredicate->WrittenBookPredicate
net.minecraft.advancements.critereonBlockPredicate现在接受一个DataComponentMatchers用于匹配任何委托的组件数据DataComponentMatchers- 一个对DataComponentGetter进行操作的谓词,匹配提供者上的任何精确和部分组件数据。EntityPredicate现在接受一个DataComponentMatchers而不是Optional<DataComponentExactPredicate>ItemPredicate现在接受一个DataComponentMatchers用于匹配任何委托的组件数据NbtPredicate#matches现在接受一个DataComponentGetter而不是ItemStackSingleComponentItemPredicate现在实现DataComponentPredicate而不是ItemSubPredicatematches(ItemStack, T)->matches(T)
net.minecraft.core.componentDataComponentPatchDELIMITED_STREAM_CODEC$CodecGetter- 获取给定组件类型的编解码器。
DataComponentPredicate->DataComponentExactPredicateisEmpty- 检查谓词内的预期组件列表是否为空。
net.minecraft.core.registries.Registries#ITEM_SUB_PREDICATE_TYPE->DATA_COMPONENT_PREDICATE_TYPE,不是一对一net.minecraft.world.item.AdventureModePredicate不再接受一个布尔值来显示在工具提示中net.minecraft.world.itemBannerItem#appendHoverTextFromBannerBlockEntityTag已移除Item#appendHoverText(ItemStack, Item.TooltipContext, List<Component>, TooltipFlag)->appendHoverText(ItemStack, Item.TooltipContext, TooltipDisplay, Consumer<Component>, TooltipFlag),现已弃用ItemStackaddToTooltip现在是公开的addDetailsToTooltip- 将物品的组件详细信息附加到工具提示。
JukeboxPlayable#showInTooltip已移除
net.minecraft.world.item.componentBlockItemStateProperties现在实现TooltipProviderChargedProjectiles现在实现TooltipProviderCustomData#itemMatcher已移除DyedItemColor#showInTooltip已移除FireworkExplosion#addShapeNameTooltip已移除ItemAttributeModifiers#showInTooltip已移除ItemContainerContents现在实现TooltipProviderSeededContainerLoot现在实现TooltipProviderTooltipDisplay- 一个组件,处理物品工具提示中应隐藏的内容。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而不是DataComponentPredicatenet.minecraft.world.level.block.Block#appendHoverText已移除net.minecraft.world.level.block.entityBannerPatternLayers现在实现TooltipProviderPotDecorations现在实现TooltipProvider
net.minecraft.world.level.saveddata.maps.MapId现在实现TooltipProvider
实体
由于 EntityPredicate 现在接受一个 DataComponentExactPredicate 来匹配实体上的槽位,一些用于实体变体的 EntitySubPredicate 已转换为存储在持有的物品上的数据组件。
net.minecraft.advancements.critereonEntityPredicate现在接受一个DataComponentExactPredicate来匹配检查的装备槽位EntitySubPredicateAXOLTOL->DataComponents#AXOLOTL_VARIANTFOX->DataComponents#FOX_VARIANTMOOSHROOM->DataComponents#MOOSHROOM_VARIANTRABBIT->DataComponents#RABBIT_VARIANTHORSE->DataComponents#HORSE_VARIANTLLAMA->DataComponents#LLAMA_VARIANTVILLAGER->DataComponents#VILLAGER_VARIANTPARROT->DataComponents#PARROT_VARIANTSALMON->DataComponents#SALMON_SIZETROPICAL_FISH->DataComponents#TROPICAL_FISH_PATTERN、TROPICAL_FISH_BASE_COLOR、TROPICAL_FISH_PATTERN_COLORPAINTING->DataComponents#PAINTING_VARIANTCAT->DataComponents#CAT_VARIANT、CAT_COLLARFROG->DataComponents#FROG_VARIANTWOLF->DataComponents#WOLF_VARIANT、WOLF_COLLARPIG->DataComponents#PIG_VARIANT- 使用变体子谓词的
register已移除 catVariant、frogVariant、wolfVariant已移除$EntityHolderVariantPredicateType、$EntityVariantPredicateType已移除
SheepPredicate不再接受DyeColor
net.minecraft.client.renderer.entity.state.TropicalFishRenderState#variant->patternnet.minecraft.core.componentDataComponentGetter- 一个从某个对象获取数据组件的获取器。DataComponentHolder、DataComponentMap现在继承DataComponentGetterDataComponentExactPredicate现在是一个DataComponentGetter的谓词expect- 一个期望数据组件具有某个值的谓词。test(DataComponentHolder)已移除
DataComponentsSHEEP_COLOR- 绵羊的染料颜色。SHULKER_COLOR- 潜影贝(盒)的染料颜色。COW_VARIANT- 奶牛的变体。CHICKEN_VARIANT- 鸡的变体。WOLF_SOUND_VARIANT- 狼发出的声音。
net.minecraft.world.entityEntity现在实现DataComponentGetterapplyImplicitComponents- 将获取器中的组件应用到实体上。这应由模组制作者覆盖。applyComponentsFromItemStack- 将堆栈中的组件应用到实体上。castComponentValue- 将对象的类型转换为组件类型。setComponent- 将组件数据设置到实体上。applyImplicitComponent- 将组件数据应用到实体上。这应由模组制作者覆盖。applyImplicitComponentIfPresent- 如果获取器中存在该组件,则应用它。
EntityType#appendCustomNameConfig->appendComponentsConfigVariantHolder接口已移除- 因此,相关实体上的所有
setVariant方法都是私有的,而关联的数据也可以从DataComponentGetter获得
- 因此,相关实体上的所有
net.minecraft.world.entity.animalCatVariant#CODECFox$Variant#STREAM_CODECFrogVariant#CODECMushroomCow$Variant#STREAM_CODECParrot$Variant#STREAM_CODECRabbit$Variant#STREAM_CODECSalmon$Variant#STREAM_CODECTropicalFishgetVariant->getPattern$Pattern现在实现TooltipProvider
Wolf->.wolf.WolfWolfVariant->.wolf.WolfVariant,现在是一个记录,接受一个$AssetInfo和一个SpawnPrioritySelectorsWolfVariants->.wolf.WolfVariants
net.minecraft.world.entity.animal.axolotl.Axolotl$Variant#STREAM_CODECnet.minecraft.world.entity.animal.horseLlama$Variant#STREAM_CODECVariant#STREAM_CODEC
net.minecraft.world.entity.animal.wolfWolfSoundVariant- 狼发出的声音。WolfSoundVariants- 所有原版狼声音变体。
net.minecraft.world.entity.decoration.PaintingVARIANT_MAP_CODEC已移除VARIANT_CODEC现在是私有的
net.minecraft.world.entity.npc.VillagerDataHolder#getVariant、setVariant已移除net.minecraft.world.entity.variant.VariantUtils- 用于获取实体变体信息的工具。net.minecraft.world.itemItemStack#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_TYPEnet.minecraft.world.entity.variantBiomeCheck- 一个生成条件,检查实体是否在给定的生物群系之一中。MoonBrightnessCheck- 一个生成条件,检查月亮的亮度。PriorityProvider- 一个基于某个优先级整数对条件选择器进行排序的接口。SpawnCondition- 检查实体是否可以在该位置生成。SpawnConditions- 可供选择的生成条件。SpawnContext- 一个包含实体生成所在的当前位置、等级和生物群系的对象。SpawnPrioritySelectors- 要针对实体检查的生成条件列表。用于在给定位置随机选择一个变体生成。StructureCheck- 一个生成条件,检查实体是否在结构内。
变体数据包注册表
青蛙、猫、奶牛、鸡、猪、狼和狼的声音变体是数据包注册表对象,意味着现在大多数引用需要通过 RegistryAccess 或 HolderLookup$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(用于标识符或纹理)正在被定义标识符以及潜在纹理路径的对象所取代。有三个主要对象需要了解:ClientAsset、ModelAndTexture 和 MaterialAssetGroup。
ClientAsset 是一个 id/纹理对,用于指向纹理位置。默认情况下,纹理路径由 id 构造,路径以 textures 为前缀,并以 PNG 扩展名为后缀。
ModelAndTexture 是一个对象/客户端资源对,当渲染器应在多个模型之间选择时使用。通常,渲染器会创建一个对象类型到模型的映射,并提供给 ModelAndTexture 的对象用作映射中的查找键。
MaterialAssetGroup 是一个处理用某些纹饰材料渲染装备资源的处理器。它接受用于叠加到盔甲上的基础纹理,以及针对给定装备资源的任何覆盖。
net.minecraft.advancements.DisplayInfo现在接受一个ClientAsset而不是仅一个ResourceLocation作为背景纹理net.minecraft.client.modelAdultAndBabyModelPair- 保存两个Model实例,表示某个实体的成年和幼年形态。ChickenModel#createBaseChickenModel- 创建默认的鸡模型。ColdChickenModel- 寒冷温度下鸡的变体模型。ColdCowModel- 寒冷温度下奶牛的变体模型。ColdPigModel- 寒冷温度下猪的变体模型。CowModel#createBaseCowModel- 创建奶牛的基础模型。PigModel#createBasePigModel- 创建默认的猪模型。WarmCowModel- 温暖温度下奶牛的变体模型。
net.minecraft.client.renderer.entityChickenRenderer现在继承MobRenderer而不是AgeableMobRendererCowRenderer现在继承MobRenderer而不是AgeableMobRendererPigRenderer现在继承MobRenderer而不是AgeableMobRenderer
net.minecraft.client.renderer.entity.layers.SheepWoolUndercoatLayer- 一个渲染绵羊羊毛底层的层。net.minecraft.client.renderer.entity.stateCowRenderState- 奶牛实体的渲染状态。SheepRenderStategetWoolColor- 返回绵羊羊毛的整数颜色。isJebSheep- 返回绵羊的名称是否包含jeb_前缀。
net.minecraft.core.ClientAsset- 一个包含标识符和指向某个纹理的路径的对象。net.minecraft.data.loot.EntityLootSubProvider#killedByFrogVariant现在接受FrogVariant的HolderGetternet.minecraft.data.tags.CatVariantTagsProvider类已移除net.minecraft.tags.CatVariantTags类已移除net.minecraft.world.entity.animalAbstractCow- 一个代表奶牛(牛)的抽象动物。Chicken#setVariant、getVariant- 处理鸡的变体信息。ChickenVariant- 一个定义给定鸡的通用可渲染信息和生物群系生成的类。ChickenVariants- 保存所有原版鸡变体的键。Cow现在继承AbstractCow。CowVariant- 一个定义给定奶牛的通用可渲染信息和生物群系生成的类。CowVariants- 保存所有原版奶牛变体的键。CatVariant(ResourceLocation)->CatVariant(ClientAsset, SpawnPrioritySelectors)CatVariants- 保存所有原版猫变体的键。FrogVariant->.frog.FrogVariantFrogVariant(ResourceLocation)->FrogVariant(ClientAsset, SpawnPrioritySelectors)
MushroomCow现在继承AbstractCowPigVariant- 一个定义给定猪的通用可渲染信息和生物群系生成的类。TemperatureVariants- 一个接口,保存指示不同温度下实体的ResourceLocation。
net.minecraft.world.entity.variant.ModelAndTexture- 定义带有其关联纹理的模型。net.minecraft.world.item.equipment.trimMaterialAssetGroup- 一个资源定义了一些基础以及基于所穿戴装备的排列。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 现在有使用 Codec 或 MapCodec 进行写入和读取的方法。对于 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#parseJsonnet.minecraft.commands.argumentsComponentArgument现在继承ParserBasedArgumentNbtTagArgument现在继承ParserBasedArgumentStyleArgument现在继承ParserBasedArgument
net.minecraft.commands.arguments.item.ItemPredicateArgument现在继承ParserBasedArgumentnet.minecraft.nbtByteArrayTag,现在是 final,不再接受列表对象ByteTag现在是一个记录CollectionTag现在是一个密封接口,不再继承AbstractList或具有泛型set、add已移除remove现在返回一个Tagget- 返回指定索引处的标签。getElementType已移除size- 返回集合的大小。isEmpty- 返回集合是否没有元素。stream- 流式传输集合的元素。
CompoundTag现在是 finalstore- 将编解码器或映射编解码器写入标签。read- 从标签中读取编解码器或映射编解码器编码的值。getFloatOrDefault、getIntOrDefault、getLongOrDefault- 获取具有关联键的值,如果不存在或抛出异常则返回默认值。storeNullable- 当不为 null 时,使用编解码器将值写入标签。putUUID、getUUID、hasUUID已移除getAllKeys->keySetvalues、forEach- 实现标准的映射操作。- 接受列表对象的
putByteArray、putIntArray已移除 getTagType已移除contains已移除get*、get*Or- 返回键的可选包装对象,如果使用Or方法,则返回指定的默认值。
DoubleTag现在是一个记录EndTag现在是一个记录FloatTag现在是一个记录IntArrayTag,现在是 final,不再接受列表对象IntTag现在是一个记录ListTag,现在是 final,继承AbstractListaddAndUnwrap- 将标签添加到列表中,如果是一个包含单个元素的复合标签,则改为添加内部标签。get*、get*Or- 返回键的可选包装对象,如果使用Or方法,则返回指定的默认值。compoundStream- 返回列表中所有CompoundTag的扁平映射。
LongArrayTag,现在是 final,不再接受列表对象LongTag现在是一个记录NbtIo#readUnnamedTag现在是公开的,用于测试NbtOps现在有一个私有构造函数NbtUtilsgetDataVersion现在有一个接受Dynamic的重载createUUID、loadUUID已移除readBlockPos、writeBlockPos已移除
NumericTag现在是一个实现PrimitiveTag的密封接口getAsLong->longValuegetAsInt->intValuegetAsShort->shortValuegetAsByte->byteValuegetAsDouble->doubleValuegetAsFloat->floatValuegetAsNumber->boxas*- 返回数值的可选包装。
PrimitiveTag- 一个密封接口,表示标签数据是一个原始对象。ShortTag现在是一个记录SnbtGrammar- 用于字符串化 NBT 的解析器创建器。SnbtOperations- 一个包含用于解析某些值的内置操作的辅助工具。StringTag现在是一个记录StringTagVisitorvisit->build,不是一对一handleEscape->handleKeyEscape,现在是私有的
Tag现在是一个密封接口as*-> 尝试将标签转换为其子类型之一,失败时返回空 optional。getAsString->asString,不是一对一
TagParser现在持有一个泛型,引用要解析到的中间对象的类型- 构造函数现在接受一个语法,或者
create从DynamicOps构造语法 AS_CODEC->FLATTENED_CODECparseTag->parseCompoundFully或parseCompoundAsArgument- 其他方法如
parseFully、parseAsArgument解析到某个中间对象 - 这些都是实例方法
- 其他方法如
readKey、readTypedValue已移除
- 构造函数现在接受一个语法,或者
TagType#isValue已移除
net.minecraft.util.parsing.packratCachedParseState- 一个缓存已解析位置并在读取时控制的解析状态。Control#hasCut- 返回语法的控制流对于读取对象是否有 cut。DelayedException- 一个创建要抛出的异常的接口。Dictionaryput现在返回一个NamedRuleput(Atom<T>, Term<S>, Rule.RuleAction<S, T>)->putComplexget->getOtThrow,不是一对一forward- 获取或写入术语到字典。namedWithAlias- 创建一个对命名原子或其别名的新引用。
ErrorCollector$Nop- 一个什么都不做的错误收集器。NamedRule- 一个具有关联名称的规则。ParseState现在是一个接口- 缓存逻辑已移至
CachedParseState scope- 返回解析对象内当前正在分析的范围。parse现在接受NamedRule而不是AtomacquireControl、releaseControl- 处理获取解析期间使用的Control。silent- 返回一个不收集任何错误的ParseState。
- 缓存逻辑已移至
Ruleparse、$RuleAction#run现在返回一个可为 null 的值,而不是 optionalSimpleRuleAction现在实现$RuleAction
Scope#pushFrame、popFrame、splitFrame、clearFrameValues、mergeFrame- 处理将解析术语管理到称为帧的部分中。Termnamed->Dictionary#named,不是一对一repeated、repeatedWithTrailingSeparator、repeatedWithoutTrailingSeparator- 处理类似于 varargs 的重复术语,并将它们放入列表中。positiveLookahead、negativeLookahead- 处理基于后续内容匹配信息的术语。fail- 将术语标记为解析期间失败。
net.minecraft.util.parsing.packrat.commandsCommandArgumentParser- 将字符串解析为与命令一起使用的参数。Grammar现在接受顶部的NamedRule而不是AtomGreedyPatternParseRule- 一个尝试贪婪匹配提供的模式的规则,假设如果某个区域匹配,则可以获得匹配的组。GreedyPredicateParseRule- 一个尝试贪婪匹配接受的字符的规则,确保字符串达到最小大小。NumberRunParseRule- 一个尝试从字符串解析数字的规则。ParserBasedArgument- 一个使用解析器提取值的命令参数。ResourceLookupRule现在接受 id 解析器的NamedRule而不是AtomStringReaderParserState现在继承CachedParsedState- 不再接受
Dictoionary
- 不再接受
StringReaderTerms#characters- 匹配字符串中的多个字符,通常用于捕获小写和大写变体。UnquotedStringParseRule- 一个将序列的一部分作为未引用字符串读取的规则,确保它达到最小大小。
保存数据,现在带有类型
SavedData 已被重写,将其大部分保存和加载逻辑抽象到单独的 SavedDataType 中。这意味着 save 覆盖以及额外的 load 和 factory 方法现在都在 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.ServerScoreboarddataFactory已移除createData现在接受一个$Packed实例
net.minecraft.world.RandomSequencesfactory、load已移除codec- 根据当前世界种子为随机序列构造一个编解码器。
net.minecraft.world.entity.raid.Raids不再接受任何参数getType- 根据当前维度返回保存数据类型。factory已移除tick现在接受ServerLevelgetId- 获取突袭实例的标识符。canJoinRaid不再接受突袭实例load不再接受ServerLevel
net.minecraft.world.level.levelgen.structure.structures.StructureFeatureIndexSavedDatafactory、load已移除type- 返回具有指定 id 的要素保存数据类型。
net.minecraft.world.level.saveddataSavedDatasave已移除$Factory记录已移除$Context- 保存保存数据正在写入的当前上下文。
SavedDataType- 一个表示保存数据类型的记录,包括关于如何构造、保存和加载数据的信息。
net.minecraft.world.level.saveddata.mapsMapIndex现在有一个接受最后一个地图 id 的构造函数factory、load已移除getFreeAuxValueForMap->getNextMapId
MapItemSavedDatafactory、load已移除type- 使用地图 id 的键返回保存数据类型。
net.minecraft.world.level.storage.DimensionDataStorage现在接受一个SavedData$ContextcomputeIfAbsent、get现在只接受SavedDataTypeset现在接受SavedDataType以及数据实例
net.minecraft.world.scores.ScoreboardSaveDataload->loadFrompack- 将数据打包到其保存数据格式中。$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 可以分别使用 createBuffer 和 createTexture 创建带有所需数据的缓冲区或包含要渲染信息的纹理。为冗余起见,缓冲区保存顶点数据,而纹理保存纹理(颜色和深度)数据。您通常应缓存缓冲区或纹理对象以供以后使用,并根据需要更新任何附加数据。作为参考,缓冲区通常通过使用 BufferBuilder 和 ByteBufferBuilder 首先构建 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);
}
然而,除非您需要如此精细的控制,否则建议在必要时使用带有 MultiBufferSource 的 RenderType,因为它会为您设置大部分内容。
对象引用
大多数用于确定模式和处理纹理的 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#writeToTexture 或 CommandEncoder#copyTextureToTexture。这要么接受要写入的 NativeImage,要么接受带有纹理数据和要使用的 NativeImage$Format 的 IntBuffer。
// 像其他缓冲区/纹理修改方法一样,这必须在渲染通道之外完成
// 我们假设您有一些要加载到纹理中的 `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_shader 和 fragment_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#process 的 RenderPass 消费者中通过调用 #setUniform 来指定它们。
// 假设我们已经得到了 `PostChain` post
post.process(Minecraft.getInstance().getMainRenderTarget(), GraphicsResourceAllocator.UNPOOLED, pass -> {
pass.setUniform("Radius", 0.4f);
});
com.mojang.blaze3d.GpuOutOfMemoryException- 当无法在 GPU 上分配纹理时抛出的异常。com.mojang.blaze3d.buffersBufferType不再存储 GL 代码,现在在GlConst#toGl中BufferUsage不再存储 GL 代码,现在在GlConst#toGl中isReadable、isWritable- 返回缓冲区是否可读或可写。
GpuBuffer现在是抽象的- 带有
ByteBuffer的构造函数已移除 size- 返回缓冲区的大小。type- 返回缓冲区的类型。resize、write、read、bind已移除usage- 返回缓冲区的用途。close现在是抽象的isClosed- 返回缓冲区是否已关闭。$ReadView现在是一个接口,定义了缓冲区数据以及如何关闭视图
- 带有
com.mojang.blaze3d.font.SheetGlyphInfo#upload现在接受一个GpuTexturecom.mojang.blaze3d.openglDirectStateAccess- 一个创建数据并将其绑定到某个帧缓冲区的接口。$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.pipelineBlendFunction- 一个类,包含在目标中叠加像素时要应用的源和目标颜色及 alpha。这也包含所有原版混合函数。CompiledRenderPipeline- 一个接口,包含具有渲染到屏幕所需所有信息的管道。RenderPipeline- 一个类,包含将某个对象渲染到屏幕所需的一切。它在应用之前类似于渲染状态。RenderTarget现在接受一个表示目标名称的字符串colorTextureId->colorTexture,现在是一个GpuTexture- 同样
getColorTextureId->getColorTexture
- 同样
depthBufferId->depthTexture,现在是一个GpuTexture- 同样
getDepthTextureId->getDepthTexture
- 同样
filterMode现在是一个FilterMode- 同样
setFilterMode用于 int 参数
- 同样
blitAndBlendToScreen不再接受视口大小参数framebufferId已移除checkStatus已移除bindWrite、unbindWrite、setClearColor已移除blitToScreen不再接受任何参数blitAndBlendToScreen->blitAndBlendToTexture,不是一对一clear已移除unbindRead已移除
com.mojang.blaze3d.platformDepthTestFunction- 一个枚举,表示在将样本渲染到帧缓冲区时要应用的受支持深度测试。DisplayData现在是一个记录withSize- 创建一个具有指定宽度/高度的新实例。withFullscreen- 创建一个具有指定全屏标志的新实例。
FramerateLimitTrackergetThrottleReason- 返回游戏帧率被限制的原因。isHeavilyThrottled- 返回当前限制是否显著影响游戏速度。$FramerateThrottleReason- 帧率被限制的原因。
GlConst->com.mojang.blaze3d.opengl.GlConst#toGl- 将某个引用对象映射到其关联的 OpenGL 代码。
GlDebug->com.mojang.blaze3d.opengl.GlDebugenableDebugCallback现在接受一组启用的扩展。
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类已移除getVendor、getRenderer、getOpenGlVersion(现在为getVersion)已移至GpuDevice上的实例抽象方法getCpuInfo->GLX#_getCpuInfo
GLXgetOpenGLVersionString已移除_init->_getCpuInfo,不是一对一_renderCrosshair、com.mojang.blaze3d.systems.RenderSystem#renderCrosshair->net.minecraft.client.gui.components.DebugScreenOverlay#render3dCrosshair,不是一对一
PolygonMode- 一个枚举,定义多边形在缓冲区中将如何渲染。NativeImage构造函数现在是公开的upload已移除getPointer- 返回指向图像数据的指针。setPixelABGR现在是公开的applyToAllPixels已移除downloadTexture、downloadDepthBuffer已移除flipY已移除setPackPixelStoreState、setUnpackPixelStoreState已移除$InternalGlFormat枚举已移除$Format不再包含 GL 代码,现在在GlConst#toGl中
TextureUtilgenerateTextureId、releaseTextureId已移除prepareImage已移除writeAsPNG现在接受一个GpuTexture而不是直接的三个整数- 没有
IntUnaryOperator的重载已移除
- 没有
com.mojang.blaze3d.resourceRenderTargetDescriptor现在接受一个表示要清除到的颜色的整数ResourceDescriptorprepare- 在分配后准备资源以供使用。canUsePhysicalResource- 通常返回一个描述符是否已经分配了相同的信息。
com.mojang.blaze3d.shadersAbstractUniform->com.mojang.blaze3d.opengl.AbstractUniformsetSafe方法已移除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现在返回一个$Typeset(int, float)已移除setSafe现在是私有的$Type- 保存类型名称以及它包含多少个值。getLocation已移除getCount->$Type#countgetIntBuffer、getFloatBuffer已移除$Type->com.mojang.blaze3d.shaders.UniformType
- 构造函数现在接受一个
com.mojang.blaze3d.systemsCommandEncoder- 一个接口,定义如何将各种命令编码到底层渲染系统,例如创建通道、清除和写入纹理,或从缓冲区读取。GpuDevice- 一个接口,定义用于绘制到屏幕的设备或底层渲染系统。它负责创建缓冲区和纹理,同时编译任何管道。RenderPass- 一个接口,定义如何使用底层渲染系统将给定的通道渲染到某个缓冲区。这允许绑定任何采样器并设置所需的统一变量。RenderSystemisOnRenderThreadOrInit、assertOnRenderThreadOrInit已移除recordRenderCall、replayQueue已移除blendFunc、blendFuncSeparate、blendEquation已移除texParameter、deleteTexture、bindTextureForSetup已移除stencilFunc、stencilMask、stencilOp已移除clearDepth已移除glBindBuffer、glBindVertexArray、glBufferData、glDeleteBuffers已移除glUniform1i已移除glUniform1、glUniform2、glUniform3、glUniform4已移除glUniformMatrix2、glUniformMatrix3、glUniformMatrix4已移除setupOverlayColor现在接受一个GpuTexture而不是两个 intbeginInitialization、finishInitialization已移除renderThreadTesselator已移除setShader、clearShader、getShader已移除setShaderTexture现在接受一个GpuTexture而不是一个绑定地址getShaderTexture现在返回一个GpuTexture,如果不存在则返回 nullpixelStore、readPixels已移除queueFencedTask、executePendingTasks- 处理发送在 GPU 上异步运行的任务。SCISSOR_STATE- 保存主要的剪裁状态。disableDepthTest、enableDepthTest已移除depthFunc、depthMask已移除enableBlend、disableBlend已移除neableCull、disableCull已移除polygonMode、enablePolygonOffset、disablePolygonOffset、polygonOffset已移除enableColorLogicOp、disableColorLogicOp、logicOp已移除bindTexture、viewport已移除colorMask、clearColor、clear已移除setupShaderLights(CompiledShaderProgram)已移除getShaderLights- 返回表示块光和天空光的向量。drawElements、getString已移除initRenderer现在接受窗口指针、默认着色器源以及一个是否使用调试标签的布尔值setupDefaultState不再接受任何参数maxSupportTextureSize已移除glDeleteVertexArrays已移除defaultBlendFunc已移除setShaderTexture已移除getQuadVertexBuffer- 返回一个绑定了一个四边形的顶点缓冲区。getDevice、tryGetDevice- 返回表示要使用的底层渲染系统的GpuDevice。getCapsString已移除activeTexture已移除setModelOffset、resetModelOffset、getModelOffset- 处理在渲染模型时应用于ModelOffset统一变量的偏移量。通常用于云和世界边界。$AutoStorageIndexBuffer#bind->getBuffer,不是一对一$GpuAsyncTask- 一个保存回调和围栏对象的记录,用于将信息同步到 GPU。
ScissorState- 一个类,保存要渲染的屏幕部分。
com.mojang.blaze3d.texturesAddressMode- 设置为如何将纹理渲染到特定位置的模式。FilterMode- 设置为当细节级别函数确定纹理应如何最大化或最小化时如何渲染纹理的模式。GpuTexture- 根据需要绑定和写入 GPU 的纹理。TextureFormat- 指定纹理应分配的格式。
com.mojang.blaze3d.vertexPoseStackmulPose(Quaternionf)、rotateAround现在接受Quaternionfc而不是Quaternionfclear->isEmptymulPose(Matrix4f)->mulPose(Matrix4fc)$PosecomputeNormalMatrix现在是私有的transformNormal现在接受Vector3fc作为其第一个参数translate、scale、rotate、rotateAround、setIdentity、mulPose现在除了在堆栈上之外,在姿势本身上也可用
VertexBuffer->com.mojang.blaze3d.buffers.GpuBuffer,不是一对一- 一些逻辑也移至
VertexFormat
- 一些逻辑也移至
VertexFormatbindAttributes已移除setupBufferState、clearBufferState、getImmediateDrawVertexBuffer->uploadImmediateVertexBuffer、uploadImmediateIndexBuffer;不是一对一$IndexType不再存储 GL 代码,现在在GlConst#toGl中$Mode不再存储 GL 代码,现在在GlConst#toGl中
VertexFormatElementsetupBufferState已移除$Type不再存储 GL 代码,现在在GlConst#toGl中$Usage不再存储 GL 函数调用,现在在VertexArrayCache#setupCombinedAttributes中
com.mojang.mathMatrixUtilisIdentity、isPureTranslation、isOrthonormal现在接受一个Matrix4fccheckProperty- 检查提供的属性是否在矩阵中表示。
OctahedralGrouptransformation现在返回一个Matrix3fcfromAnges->fromXYAngles,不是一对一
Quadrant- 一个包含 90 度增量旋转的枚举。SymmetricGroup3#transformation现在返回一个Matrix3fcTransformation现在接受一个Matrix4fcgetMatrix现在返回一个Matrix4fcgetMatrixCopy- 返回当前矩阵的深拷贝。
net.minecraft.client.gui.font.FontTexture现在接受一个提供的标签字符串net.minecraft.client.main.GameConfig现在接受一个布尔值,表示是否渲染调试标签net.minecraft.client.rendererCloudRenderer#render不再接受用于投影或姿势的Matrix4fCompiledShaderProgram->com.mojang.blaze3d.opengl.GlProgramlink现在接受一个字符串作为着色器名称setupUniforms现在接受$UniformDescription列表以及采样器使用的名称列表getUniformConfig已移除bindSampler现在接受一个GpuTexture而不是整数绑定标识符parseUniformNode已移除
CoreShaders->RenderPipelines,不是一对一LightTexture#getTarget- 返回包含基于玩家的当前等级的光照纹理的GpuTexture。PostChainload不再接受ShaderManager,现在接受一个表示链名称的ResourceLocationaddToFrame、process现在接受一个RenderPass消费者,用于将任何其他设置应用于要渲染的通道setUniform已移除setOnRenderPass- 在RenderPass上的后处理链中设置统一变量,以供着色器使用。
PostChainConfig$Pass现在接受顶点和片段着色器的 id,而不是程序 idreferencedTargets- 返回通道中引用的要应用的目标。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不再接受VertexFormat或VertexFormat$ModeSKY、END_SKY、sky、endSky、stars已移除ENTITY_OUTLINE_BLIT、entityOutlineBlit已移除PANORAMA、panorama已移除CREATE_LIGHTMAP、createLightmap已移除createClouds、flatClouds、clouds、cloudsDepthOnly已移除worldBorder已移除debugLine- 返回与调试线关联的RenderType。entityOutlineBlit- 返回用于渲染实体轮廓的RenderType。panorama- 返回用于渲染全景模式的RenderType。createLightmap- 返回用于渲染光照图纹理的RenderType。create不再接受VertexFormat或VertexFormat$Mode,而是接受RenderPipelinegetRenderTarget、getRenderPipeline- 返回用于渲染的目标和管道。format、mode、draw现在是抽象的$CompositeStateBuilder方法现在是 protected$OutlineProperty现在是 protected
ShaderDefines$Builder#define现在有一个接受整数的重载ShaderManagerSHADER_INCLUDE_PATH现在是私有的MAX_LOG_LENGTH已移除preloadForStartup已移除,被GpuDevice#precompilePipeline取代getProgram、getProgramForLoading->getShader,不是一对一linkProgram现在接受RenderPipeline而不是ShaderProgram和ShaderProgramConfig$CompilationCache#getOrCompileProgram、getOrCompileShader->getShaderSource,不是一对一$Configs不再接受程序映射$ShaderCompilationKey记录已移除
ShaderProgram、ShaderProgramConfig->RenderPipeline,不是一对一SkyRenderer#renderDarkDisc不再接受PoseStack
net.minecraft.client.renderer.chunk.SectionRenderDispatcheruploadSectionLayer、uploadSectionIndexBuffer->$RenderSection#uploadSectionLayer、uploadSectionIndexBuffer$SectionBuffers- 一个保存用于渲染部分的缓冲区的类。
net.minecraft.client.renderer.textureAbstractTextureNOT_ASSIGNED已移除texture、getTexture- 保存要渲染的纹理的引用。getId、releaseId已移除bind已移除
DynamicTexture现在接受纹理的标签SpriteContents#uploadFirstFrame、$AnimatedTexture#uploadFirstFrame现在接受一个GpuTextureSpriteTicker#tickAndUpload现在接受GpuTextureTextureAtlasSprite#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 构建模型组,并加载纹理,从而进入实际烘焙 BlockStateModel 和 ItemModel 的最后一步。这通过 $UnbakedRoot(或 $Unbaked)和 ModelBakery 上提供的 bake 方法处理。简而言之,bake 构建 BakedQuad 列表,其中包含方块状态或物品模型本身所需的任何其他信息。ResolvedModel 从烘焙器中获得,然后调用其实例方法。对于 BlockStateModel,这通过 SimpleModelWrapper#bake 解析,从中从 Variant 数据获得 ModelState。它们将烘焙的四边形存储在 BlockModelPart 中。对于 ItemModel,它直接使用 BakedQuad 列表以及由 ModelRenderProperties#fromResolvedModel 提供的信息。这确实意味着每个 BlockStateModel 和 ItemModel 如果同一个模型在多个位置被引用,则可能包含重复(但唯一)的 BakedQuad。
方块生成器:变体修改器
鉴于所有分离出方块状态 JSON 加载的变化,BlockModelGenerators 也有许多变化。虽然其中大部分只是重命名(例如,BlockStateGenerator -> BlockModelDefinitionGenerator),但主要变化是增加了 VariantMutator。VariantMutator 在功能上是 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.modelsBlockModelGeneratorsnonOrientableTrapdoor->NON_ORIENTABLE_TRAPDOOR,现在是静态的- 常量现在可用于常见的
VariantMutator,例如将方块模型旋转一定角度 texturedModels->TEXTURED_MODELS,现在是静态的MULTIFACE_GENERATOR现在是私有的plainModel- 从模型位置创建一个变体。variant、variants- 从一些Variant创建一个常规的MultiVariantplainVariant- 从其位置创建一个只有一个模型的MultiVariant。condition- 为多部分模型创建一个新的条件构建器or- 对多个条件进行 OR 操作。- 大多数生成器方法现在返回
BlockModelDefinitionGenerator、Variant或MultiVariant,并接受一个Variant或MultiVariant而不是指向所需模型的ResourceLocationVariantProperties已被VariantMutator取代Condition$TerminalCondition被Condition取代
createHorizontalFacingDispatch、createHorizontalFacingDispatchAlt、createTorchHorizontalDispatch已移除createFacingDispatch已移除createRotatedVariant(Block, ResourceLocation)已移除selectMultifaceProperties- 基于提供的BlockState和方向到属性函数,创建一个属性到VariantMutator的映射。applyRotation不再接受Variant,并返回一个VariantMutator
ItemModelGenerators#generateSpawnEgg已移除ModelProvider#saveAll已移除
net.minecraft.client.data.models.blockstatesBlockStateGenerator->BlockModelDefinitionGenerator,不是一对一Condition->net.minecraft.client.renderer.block.model.multipart.Condition,不是一对一validate->instantiate,不是一对一
ConditionBuilder- 使用属性值构建一个条件MultiPartGenerator现在实现BlockModelDefinitionGeneratorwith(List<Variant>)->with(MultiVariant)with(Variant)已移除with(Condition, ...)->with(Condition, MultiVariant)- 接受
ConditionBuilder的重载
- 接受
$ConditionalEntry、$Entry已移除
MultiVariantGenerator现在实现BlockModelDefinitionGeneratormultiVariant->dispatchmultiVariant(Block, ...)->dispatch(Block, MultiVariant)$Empty- 一个匹配每个方块状态的多变体条目。
PropertyDispatch有一个包含分派值的泛型- 泛型
V替换了所有List<Variant>的值 property、properties->initial或modify$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.blockBlockModelShaper#stateToModelLocation、statePropertiesToString已移除BlockRenderDispatcher#renderBatched现在接受一个BlockModelPart列表而不是RandomSourceModelBlockRenderertesselateBlock、tesselateWithAO、tesselateWithoutAO不再接受RandomSource,并将BlockStateModel替换为BlockModelPart列表renderModel现在是静态的,不再接受BlockState$AmbientOcclusionFace->$AmbientOcclusionRenderStorage$CommonRenderStorage- 一个类,保存用于在其给定位置渲染方块的一些元数据。$SizeInfo现在接受直接索引,而不是从其方向和翻转布尔值计算信息
net.minecraft.client.renderer.block.modelBakedQuad现在是一个记录BlockElement现在是一个记录from、to现在是Vector3fc
BlockElementFace现在接受一个Quadrant作为面旋转getU、getV- 返回旋转后的纹理坐标。$Deserializer#getTintIndex现在是私有的和静态的
BlockFaceUV->BlockElementFace$UVs,不是一对一BlockModel现在是一个记录,接受一个UnbakedGeometry而不是直接的BlockElement列表$Deserializer#getElements现在返回一个UnbakedGeometry
BlockModelDefinition现在是一个记录,接受$SimpleModelSelectors和$MultiPartDefinitionGSON、fromStream、fromJsonElement->CODEC,不是一对一instantiate现在接受一个提供的字符串而不是直接的字符串$Deserializer已移除$MultiPartDefinition- 一个记录,保存用于获取多部分模型的选择器列表。$SimpleModelSelectors- 一个记录,保存变体到其未烘焙模型实例的映射。
BlockModelPart- 方块的烘焙模型表示。BlockStateModel- 方块状态的烘焙表示。collectParts- 获取用于渲染此状态的烘焙模型列表。$SimpleCachedUnbakedRoot- 一个类,表示某个$Unbaked模型的委托。$Unbaked- 一个可以创建$SimpleCachedUnbakedRoot的$UnbakedRoot的扩展
FaceBakerybakeQuad现在接受Vector3fc而不是Vector3frecomputeUVs已移除extractPositions- 提取面的位置并将它们传递给一个消费者以供使用。
ItemTransform现在是一个记录,向量是Vector3fcMultiVariant->net.minecraft.client.data.models.MultiVariantCODECwith- 创建一个带有指定修改器的MultiVariant。$Deserializer类已移除
SimpleModelWrapper现在实现BlockModelPartSimpleUnbakedGeometry- 一个保存要烘焙的BlockElement列表的未烘焙几何体。SingleVariant- 一个BlockStateModel实现,其状态只有一个模型。UnbakedBlockStateModel->BlockStateModel$UnbakedRootVariant不再实现ModelState,现在接受$SimpleModelState而不是直接的旋转和 uv 锁定- 构造函数现在有一个只提供
ResourceLocation的重载,不再接受权重,将其留给MultiVariant CODECwithXRot、withYRot、withUvLock、withModel、withState、with- 将变体变异为一个应用了给定设置的新对象。$Deserializer类已移除$SimpleModelState- 一个记录,保存 x/y 旋转和 uv 锁定。
- 构造函数现在有一个只提供
VariantMutator- 一个变体上的一元运算符,将指定设置应用于变体。在状态生成期间使用。
net.minecraft.client.renderer.block.model.multipartAndCondition、OrCondition->CombinedCondition,不是一对一KeyValueCondition现在是一个记录,接受一个要测试的键到术语的映射MultiPart->MultiPartModel$Unbaked$DefinitionCODECgetMultiVariants已移除
$Deserializer类已移除
Selector现在是一个记录,接受一个BlockStateModel$Unbaked而不是MultiVariant$Deserializer类已移除
net.minecraft.client.renderer.entity.ItemRendererrenderItem现在接受一个List<BakedQuad>而不是BakedModelrenderStatic不再接受一个表示物品握在哪只手中的布尔值
net.minecraft.client.renderer.itemBlockModelWrapper现在有一个公共构造函数,接受染色源列表、四边形列表和ModelRenderProperties- 四边形列表和
ModelRenderProperties取代了直接的BakedModel,或者现在的BlockStateModel computeExtents- 将烘焙四边形的顶点提取到一个数组中。
- 四边形列表和
ItemModel$BakingContext#bake已移除ItemModelResolver#updateForLiving、updateForTopItem不再接受表示物品是否在左手中的布尔值ItemStackReenderStateisGui3d已移除transform已移除visitExtents- 访问模型要渲染的所有顶点,并将它们传递给提供的消费者。$LayerRenderStateNO_EXTENTS_SUPPLIER- 一个空的顶点列表。setupBlockModel已被拆分为prepareQuadList、setRenderType、setUsesBlockLight、setExtents、setParticleIcon、setTransformsetupSpecialModel不再接受基础BakedModel
MissingItemModel现在接受一个BakedQuad列表和ModelRenderProperties,而不是直接的BakedModelModelRenderProperties- 用于渲染模型的属性,通常从ResolvedModel检索。SpecialModelRenderer现在接受ModelRenderProperties而不是基础BakedModel
net.minecraft.client.resources.modelBakedModel->net.minecraft.client.resources.model.QuadCollection,不是一对一BlockModelRotationby现在接受Quadrant而不是整数withUvLock- 返回带有旋转和声明锁定 UV 用于旋转的模型状态。
BlockStateDefinitions- 一个用于创建方块名称到其状态定义映射的管理器。BlockStateModelLoaderModelResourceLocation字段已移除loadBlockState不再接受缺失模型$LoadedModel类已移除$LoadedModels现在接受一个BlockStateModel$UnbakedRoot而不是$UnbakedforResolving、plainModels已移除
DelegateBakedModel->net.minecraft.client.renderer.block.model.SimpleModelWrapper,不是一对一MissingBlockModel#VARIANT已移除ModelBakerbake->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>,而是使用debugNameModelDiscoveryregisterSpecialModels已移除discoverDependencies现在是私有的getReferencedModels、getUnreferencedModels已移除addSpecialModel- 将一个根模型添加到任意加载的模型列表中。missingModel- 返回缺失模型resolve- 解析所有模型依赖关系,返回模型名称到其模型的映射。
ModelGroupCollector$GroupKey#create现在接受一个BlockStateModel$UnbakedRoot而不是$UnbakedModelManagergetModel已移除getMissingModel->getMissingBlockStateModel$ResolvedModels- 一个包含已解析依赖关系的模型的映射。
ModelResourceLocation记录已移除ModelStategetRotation->transformationisUvLocked已移除faceTransfomration、inverseFaceTransformation- 处理返回用于烘焙面顶点的变换后的Matrix4fc。
MultiPartBakedModel->net.minecraft.client.renderer.block.model.multipart.MultiPartModel- 现在实现
BlockStateModel而不是继承DelegateBakedModel $SharedBlockState- 一个持有者,包含映射到其$Selector的BlockStateModel。
- 现在实现
QuadCollection- 一个包含要基于关联方向和剔除渲染的四边形列表的数据对象。ResolvableModel$Resolver#resolve->markDependency,不是一对一- 不再直接解析,而是标记依赖关系以供后续后处理步骤使用
ResolvedModel- 一个UnbakedModel,其模型和纹理依赖关系已被完全解析。SimpleBakedModel->net.minecraft.client.renderer.block.model.SimpleModelWrapper或net.minecraft.client.renderer.block.model.SimpleUnbakedGeometry,不是一对一SpriteGetterget、reportMissingReference现在接受ModelDebugNameresolveSlot- 将TextureSlot中的键解析为其TextureAtlasSprite。
UnbakedGeometry- 一个接口,构造在烘焙时要渲染的四边形集合。UnbakedModel不再实现ResolvableModelDEFAULT_AMBIENT_OCCLUSION、DEFAULT_GUI_LIGHT已移除PARTICLE_TEXTURE_REFERENCE- 保存表示粒子纹理的键。bake已移除getAmbientOcclusion->ambientOcclusiongetGuiLight->guiLightgetTransforms-transformsgetTextureSlots-textureSlotsgeometry- 保存表示模型元素的未烘焙几何体。getParent->parent,不是一对一bakeWithTopModelValues已移除getTopTextureSlots、getTopAmbientOcclusion、getTopGuiLight、getTopTransform、getTopTransforms已移除
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.entityEntityReference- 一个对实体的引用,要么通过其在世界中的实体实例,要么通过 UUID。LivingEntity#lastHurtByPlayer、lastHurtByMob现在是EntityReferenceOwnableEntitygetOwnerUUID->getOwnerReference,不是一对一level现在返回一个Level而不是EntityGetter
TamableAnimal#setOwnerUUID->setOwner或setOwnerReference;不是一对一
net.minecraft.world.entity.animal.horse.AbstractHorse#setOwnerUUID->setOwner,不是一对一net.minecraft.world.level.Level现在实现UUIDLookup<Entity>net.minecraft.world.level.entityEntityAccess现在实现UniquelyIdentifyableUniquelyIdentifyable- 一个声称对象具有 UUID 并跟踪对象是否被移除的接口。UUIDLookup- 一个通过 UUID 查找类型的接口。
解作用域玩家参数
许多接受 Player 的方法已被解作用域,根据用例接受 LivingEntity 或 Entity。以下方法是此情况的非详尽列表。
net.minecraft.world.entity.EntityTypespawncreateDefaultStackConfig、appendDefaultStackConfigappendCustomEntityStackConfig、updateCustomEntityTag
net.minecraft.world.itemBucketItem#playEmptySoundDispensibleContainerItem#checkExtraContent、emptyContents
net.minecraft.world.levelLevelplaySeededSoundmayInteract
LevelAccessorplaySoundlevelEvent
net.minecraft.world.level.blockBucketPickup#pickupBlockLiquidBlockContainer#canPlaceLiquid
net.minecraft.world.level.block.entity.BrushableBlockEntity#brush
组件交互事件
MutableComponent 上的点击和悬停事件已被重做为类似 MapCodec 注册表的系统。它们现在都是接口,将其编解码器注册到一个 $Action 枚举。然后,该实现创建一个引用 $Action 类型的编解码器,并存储逻辑应用所需的任何必要信息。然而,没有与组件交互关联的直接“动作”逻辑。相反,它们被硬编码到它们的使用位置。对于点击事件,是在 Screen#handleComponentClicked 中。对于悬停事件,是在 GuiGraphics#renderComponentHoverEffect 中。因此,任何添加的额外事件都需要注入到枚举以及这两个位置之一或两者中。
net.minecraft.network.chatClickEvent现在是一个接口getAction->actiongetValue现在根据需要在其子类上,用于其各自的类型
HoverEvent现在是一个接口getAction->action$EntityTooltipInfoCODEC现在是一个MapCodeclegacyCreate已移除
$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.ItemModelGeneratorsSLOT_*->TRIM_PREFIX_*,现在是公开的,并且是ResourceLocationTRIM_MATERIAL_MODELS现在是公开的generateTrimmableItem现在接受ResourceLocation而不是String$TrimMaterialData现在是公开的,接受MaterialAssetGroup而不是名称和覆盖材质
net.minecraft.client.rendererMaterialMapper- 一个存储图集纹理位置和应用于纹理中 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.atlasSpriteSource#type->codec,不是一对一SpriteSources现在包含类似于客户端注册表的逻辑,通过其 id 映射器SpriteSourceType记录已移除
net.minecraft.client.renderer.texture.atlas.sourcesDirectoryLister现在是一个记录PalettedPermutations现在是一个记录SingleFile现在是一个记录SourceFilter现在是一个记录Unstitcher现在是一个记录$Region现在是公开的
net.minecraft.client.resources.model.AtlasIds- 一个保存所有原版纹理图集的ResourceLocation的类。
注册表上下文交换器
客户端物品现在存储一个 RegistryContextSwapper,用于正确检查访问注册表对象的客户端物品信息。在等级加载之前,它会获得一个占位符以避免崩溃,并在渲染期间用正确的值填充。
net.minecraft.client.multiplayerCacheSlot- 一个包含从某个上下文计算出的值的对象。更新时,先前的值被覆盖,上下文注册该槽位以进行清理。ClientLevel现在实现CacheSlot$Cleaner
net.minecraft.client.renderer.itemClientItem现在可以接受一个可为 null 的RegistryContextSwapperwithRegistrySwapper- 在ClientItem中设置RegistryContextSwapper
ItemModel$BakingContext现在接受一个RegistryContextSwapper
net.minecraft.utilPlaceholderLookupProvider- 一个包含引用对象的占位符的提供者。在客户端物品中使用,因为它们将在RegistyAccess填充之前加载。RegistryContextSwapper- 一个用于将某个对象换成另一个不同对象的接口。由客户端物品用于将占位符换成加载的RegistryAccess。
重载实例创建
重载实例已被稍微重新排列。SimpleReloadInstance 基础现在只接受 List<PreparableReloadListener>,其他字段被传入 of 函数,以便可以立即调用 #startTasks。
net.minecraft.server.packs.resourcesProfiledReloadInstance构造函数现在是私有的,通过of访问SimpleReloadInstance只接受List<PreparableReloadListener>of现在返回一个ReloadInstance,不是一对一allPreparations现在是包私有的allDone现在是私有的startTasks- 开始重载监听器。prepareTasks- 运行执行器并设置读取和加载所有所需数据所需的 future。StateFactory$SIMPLE- 一个调用PreparableReloadListener#reload的工厂
方块效果应用器
当实体在方块内部时应用于实体的效果现在通过 InsideBlockEffectApplier 和 InsideBlockEffectType 处理。InsideBlockEffectType 是一个枚举,包含一个消费者,用于在调用时应用到实体上。另一方面,InsideBlockEffectApplier 存储在实体上,作为一种基于枚举序数以有序方式应用效果的方法。
要调用其中一种效果类型,您必须覆盖 BlockBehaviour#entityInside 或 Fluid#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.entityInsideBlockEffectApplier- 一个接口,定义实体在给定方块内时应如何交互。InsideBlockEffectType- 一个枚举,定义当在引用该类型的特定方块内部时要执行的行为。
net.minecraft.world.level.block.state.BlockBehaviour#entityInside、$BlockStateBase#entityInside现在接受一个InsideBlockEffectAppliernet.minecraft.world.level.material.Fluid#entityInside、FluidState#entityInside- 每当实体被认为在流体的边界框内时调用的方法。
定时器回调,加入编解码器俱乐部!
用于在服务器计划中执行事件的 TimerCallback,通常是数据包中的 mcfunctions,现在已被重做为编解码器形式。这意味着可以通过将 MapCodec 传递给 TimerCallbacks#register(通过 TimerCallbacks#SERVER_CALLBACKS)而不是序列化器,将回调注册到可用回调列表中。
net.minecraft.world.level.timersFunctionCallback现在是一个记录FunctionTagCallback现在是一个记录TimerCallbackcodec- 返回用于序列化的编解码器。$Serializer类已移除
TimerCallbacksserialize、deserialize->codec,不是一对一
JOML 后端接口
Mojang 选择通过传递其逻辑对象的实现接口(通常附加一个 c)来减少对 JOML 对象的限制。例如,Vector3f 变成 Vector3fc,Matrix4f 变成 Matrix4fc。这不会改变任何逻辑本身,因为 c 接口由类组件实现。
标签变更
minecraft:worldgen/biomespawns_cold_variant_farm_animalsspawns_warm_variant_farm_animals
minecraft:blocksword_instantly_minesreplaceable_by_mushroomsplays_ambient_desert_block_soundsedible_for_sheepdead_bush_may_place_on->dry_vegetation_may_place_oncamels_spawnable_on
minecraft:cat_variant已移除minecraft:entity_typecan_equip_saddlecan_wear_horse_armor
minecraft:itembook_cloning_targeteggsflowers
状态效果字段重命名
一些状态效果已重命名为其游戏内名称,而不是某些内部描述符。
MOVEMENT_SPEED->SPEEDMOVEMENT_SLOWDOWN->SLOWNESSDIG_SPEED->HASTEDIG_SLOWDOWN->MINING_FATIGUEDAMAGE_BOOST->STRENGTHHEAL->INSTANT_HEALTHHARM->INSTANT_DAMAGEJUMP->JUMP_BOOSTCONFUSION->NAUSEADAMAGE_RESISTANCE->RESISTANCE
非常技术性的变更
这是一个技术变更列表,根据您的具体设置可能导致高度特定的错误。
-
minecraft:patch_sugar_cane功能和minecraft:patch_pumpkin功能的顺序已交换(先南瓜,后甘蔗),这意味着生成这两个功能的模组生物群系需要将其 JSON 更新为新顺序。 -
几个原版橡树和树选择器功能现在末尾附加了
_leaf_litter。- 例如:
trees_birch_and_oak->trees_birch_and_oak_leaf_litter
- 例如:
新增列表
net.minecraftChatFormatting#COLOR_CODECCrashReportCategory#populateBlockLocationDetails- 将方块位置详细信息添加到崩溃报告。
net.minecraft.advancements.critereon.MinMaxBounds#createStreamCodec- 为MinMaxBounds实现构造一个流编解码器。net.minecraft.client.Options#startedCleanly- 设置游戏上次启动时是否干净启动。net.minecraft.client.data.modelsBlockModelGenerators#createSegmentedBlock- 生成一个具有水平旋转的多部分方块状态定义,根据某个整数属性显示最多四个模型。ItemModelGenerators#prefixForSlotTrim- 为某个槽位中的纹饰生成一个原版ResourceLocation。
net.minecraft.client.MouseHandlerfillMousePositionDetails- 将有关当前鼠标位置和屏幕大小的详细信息添加到崩溃报告。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.buildersMeshDefinition#apply- 在返回新实例之前将给定的变换器应用于网格。MeshTransformer#IDENTITY- 执行恒等变换。
net.minecraft.client.multiplayer.ClientPacketListener#decoratedHashOpsGenenerator- 返回用于创建数据组件及其值的哈希值的生成器。net.minecraft.client.particleFallingLeavesParticle$TintedLeavesProvider- 一个FallingLeavesParticle的提供者,使用粒子生成位置上方的方块指定的颜色。FireflyParticle- 一个在给定的非空气方块位置周围生成萤火虫的粒子。
net.minecraft.client.rendererBiomeColors#getAverageDryFoliageColor- 返回干燥生物群系的平均树叶颜色。LevelRenderer$BrightnessGetter- 一个在给定方块位置获取打包亮度的接口。WorldBorderRenderer#invalidate- 使世界边界的当前渲染无效,以便重新渲染。
net.minecraft.client.renderer.entityEntityRenderDispatcher#getRenderer- 从渲染状态上存储的数据中获取要使用的渲染器。EntityRenderer#extractAdditionalHitboxes- 当启用“显示碰撞箱”调试状态时,获取要渲染的任何其他碰撞箱。
net.minecraft.client.renderer.entity.stateEntityRenderStateentityType- 实体的类型。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.selectComponentContents- 一个开关情况属性,作用于数据组件内的内容。SelectItemModelProperty#valueCodec- 返回属性类型的Codec。
net.minecraft.client.resources.DryFoliageColorReloadListener- 一个加载干燥树叶颜色图的重新加载监听器。net.minecraft.commands.arguments.ComponentArgument#getResolvedComponent- 构造一个包含其内容已解析信息的组件。net.minecraft.coreDirection#getUnitVec3f- 返回方向的浮点单位向量。HolderGetter$Provider#getOrThrow- 从资源键获取一个持有者引用。SectionPos#sectionToChunk- 将压缩的部分位置转换为压缩的区块位置。Vec3i#STREAM_CODEC
net.minecraft.networkHashedPatchMap- 一个记录,包含组件到其哈希类型/值的映射,以及一组已移除的组件。HashedStack- 一个ItemStack表示,对存储的组件进行哈希处理。ProtocolInfo$DetailsProvider- 为给定的协议提供详细信息。SkipPacketDecoderException- 当解码期间发生错误时抛出的异常,其数据被忽略。SkipPacketEncoderException- 当编码期间发生错误时抛出的异常,其数据被忽略。
net.minecraft.network.chatLastSeenMessagescomputeChecksum- 计算表示所有消息签名的合并校验和的字节。$Update#verifyChecksum- 验证更新校验和是否与最后看到的消息中的校验和匹配。
LastSeenMessagesValidator$ValidationException- 如果无法验证消息则抛出的异常。MessageSignaturedescribe- 返回消息签名的字符串化版本。checksum- 将签名中的字节哈希为单个整数。
PlayerChatMessage#describeSigned- 返回聊天消息的字符串化版本。
net.minecraft.network.codecByteBufCodecsLONG_ARRAYlengthPrefixed- 返回一个将缓冲区大小限制为给定大小的操作。
IdDispatchCodec$DontDecorateException- 一个接口,告诉异常处理程序重新抛出原始异常,而不是将其包装在EncoderException中。
net.minecraft.network.protocolCodecModifier- 一个使用给定对象修改某个编解码器的函数。ProtocolInfoBuilder#context*Protocol- 使用给定的上下文构建一个UnboundProtocol,用于修改要发送的编解码器。
net.minecraft.network.protocol.game.GameProtocolsHAS_INFINITE_MATERIALS- 一个修饰符,检查ServerboundSetCreativeModeSlotPacket中玩家是否具有必要的设置。如果没有,则丢弃数据包。$Context- 返回数据包用于修改传入编解码器的上下文。
net.minecraft.resources.DelegatingOps$DelegateListBuilder- 一个列表构建器,如果需要可以被子类化。$DelegateRecordBuilder- 一个记录构建器,如果需要可以被子类化。
net.minecraft.server.bossevents.CustomBossEvent$Packed- 一个记录,支持用于序列化的事件信息。net.minecraft.server.commands.InCommandFunction- 一个接受某些输入并返回结果的命令函数。net.minecraft.server.levelDistanceManager#forEachBlockTickingChucnks- 为每个启用了方块Tick的区块应用提供的消费者。ServerLevelareEntitiesActuallyLoadedAndTicking- 返回实体管理器是否实际上正在Tick并加载给定区块中的实体。tickThunder- 在给定等级内Tick雷声逻辑。anyPlayerCloseEnoughForSpawning- 如果玩家足够接近以在给定位置生成实体,则返回。
ServerPlayer$RespawnConfig- 一个包含玩家重生信息的记录。
net.minecraft.utilAbstractListBuilder- 一个 ops 列表构建器,将实现简化为三个方法:初始化、追加和构建最终列表。Brightnessblock- 从打包值中返回块光。sky- 从打包值中返回天空光。
HashOps- 一个为数据生成哈希码的动态 ops。ExtraCodecsUNTRUSTED_URI- 一个不受游戏信任的 URI 的编解码器。CHAT_STRING- 聊天消息中字符串的编解码器。legacyEnum- 一个将枚举映射到其在Enum#toString中的输出的编解码器。
FileSystemUtil- 一个用于与文件系统交互的工具。GsonHelper#encodesLongerThan- 返回提供的元素是否可以用指定数量的字符写入。Unit#STREAM_CODEC- 一个用于单位实例的流编解码器。UtilmapValues- 使用给定的函数更新映射的值。mapValuesLazy- 使用给定的函数更新映射的值,但每个值在首次访问时解析。growByHalf- 返回一个整数乘以 1.5,向下取整,将值钳制到某个最小值和最大整数大小。
net.minecraft.util.random.Weighted#map、WeightedList#map- 将存储的对象转换为新类型。net.minecraft.util.thread.ParallelMapTransform- 一个辅助工具,用于并行处理和批处理任务。net.minecraft.world.effect.MobEffectInstance#withScaledDuration- 构造一个新的实例,其持续时间按某个浮点值缩放。net.minecraft.world.entityAreaEffectCloud#setPotionDurationScale- 设置药水应应用的持续时间比例。DropChances- 一个槽位到概率的映射,表示实体掉落该装备的可能性。EntityisInterpolating- 返回实体是否在两个步骤之间插值。sendBubbleColumnParticles- 从服务器生成气泡柱粒子。canSimulateMovement- 实体的移动是否可以模拟,通常来自玩家。propagateFallToPassengers- 将载具的坠落伤害传播给其乘客。lavaIgnite- 如果实体不免疫,则点燃实体 15 秒。clearFreeze- 将实体被冻结的刻数设置为 0。removeLatestMovementRecordingBatch- 从本Tick执行的所有移动中删除最后一个元素。
InterpolationHandler- 一个旨在根据需要轻松处理给定实体的位置和旋转插值的类。LivingEntitygetLuck- 返回实体在随机事件中的运气。getLastHurtByPlayer、setLastHurtByPlayer- 处理最后伤害此实体的玩家。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.PlayerpreventsBlockDrops- 玩家是否不能掉落任何被破坏的方块。gameMode- 返回玩家的当前游戏模式。debugInfo- 将关于玩家的常见信息作为单个字符串返回。
net.minecraft.world.inventoryContainerSynchronizer#createSlot- 创建一个表示对侧槽位的RemoteSlot。RemoteSlot- 一个表示对侧数据的槽位,当数据不一致时进行同步。
net.minecraft.world.itemEitherHolder#key- 返回持有的注册表对象的资源键。Item#STREAM_CODECItemStackOPTIONAL_UNTRUSTED_STREAM_CODECMAP_CODECcanDestroyBlock- 返回此物品是否可以破坏提供的方块状态。
net.minecraft.world.item.alchemy.PotionContents#getPotionDescription- 返回带有某些放大器的状态效果的描述。net.minecraft.world.item.craftingRecipe#KEY_CODECTransmuteResult- 一个配方结果对象,表示一个物品、数量和应用到的组件。
net.minecraft.world.item.equipment.trim.ArmorTrim#layerAssetId- 返回纹饰资源的位置。net.minecraft.world.levelBlockGetter$BlockStepVisitor- 一个消费者,接受当前位置以及期望行进路径内的碰撞次数。ColorMapColorUtil- 一个辅助工具,根据生物群系的温度、降水、颜色映射和默认颜色从地图中获取颜色。DryFoliageColor- 用于具有干燥树叶的生物群系的颜色解析器。GameRulesgetType- 从其键获取游戏规则类型。keyCodec- 为游戏规则类型的键创建编解码器。
LevelisMoonVisible- 返回月亮当前是否在天空中可见。getPushableEntities- 获取指定目标之外的在提供的边界框内的所有实体。getClientLeafTintColor- 返回指定位置的树叶染色颜色。playPlayerSound- 在客户端向当前玩家播放声音。
LevelReader#getHeight- 返回地图在给定位置的高度。NaturalSpawner#INSCRIBED_SQUARE_SPAWN_DISTANCE_CHUNK- 提供玩家足够接近以进行生成的最小距离。
net.minecraft.world.level.biomeBiomegetDryFoliageColor、getDryFoliageColorFromTexture- 获取生物群系的干燥树叶颜色,要么从效果中获取,要么从气候设置中获取。
BiomeSpecialEffects#getDryFoliageColorOverride、$Builder#dryFoliageColorOverride- 当不从颜色映射纹理中提取时,返回默认的干燥树叶颜色。
net.minecraft.world.level.blockBaseFireBlock#fireIgnite- 点燃一个实体。BlockUPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS- 一个标志,在更新方块实体时跳过所有潜在的副作用。UPDATE_SKIP_ALL_SIDEEFFECTS- 一个标志,通过跳过某些方块实体逻辑、抑制掉落和更新已知形状来跳过所有副作用。UPDATE_SKIP_ON_PLACE- 一个标志,在设置时跳过调用BlockState#onPlace。
BonemealableBlock#hasSpreadableNeighbourPos、findSpreadableNeighbourPos- 处理在施骨粉时植被可以传播到的其他位置。CactusFlowerBlock- 生长在仙人掌上的花。FireflyBushBlock- 一个在其周围生成萤火虫粒子的灌木。SandBlock- 一个可以播放环境声音的彩色沙子方块。SegmentableBlock- 一个通常可以分解成具有独特大小和位置的部分的方块。ShortDryGrassBlock- 一个已经干枯的单个草方块。TallDryGrassBlock- 一个已经干枯的双高草方块。TerracottaBlock- 一个可以播放环境声音的陶瓦方块。TintParticleLeavesBlock- 一个其粒子被染色的树叶方块。UntintedParticleLeavesBlock- 一个其粒子未被染色的树叶方块。VegetationBlock- 一个表示某种植被的方块,可以传播光线,并需要某种耕地或泥土才能生存。
net.minecraft.world.level.block.entity.StructureBlockEntity#isStrict、setStrict- 在生成结构时设置严格模式。net.minecraft.world.level.block.sounds.AmbientDesertBlockSoundsPlayer- 一个辅助工具,用于为给定的方块播放声音,通常在animateTick期间。net.minecraft.world.level.block.state.BlockBehaviour#getEntityInsideCollisionShape- 获取实体在其内部时方块的碰撞形状。net.minecraft.world.level.border.WorldBorderclosestBorder- 根据玩家的水平方向返回离玩家最近的边界列表。$DistancePerDirection- 一个记录,包含给定方向上世界边界到实体的距离。
net.minecraft.world.level.chunk.status.ChunkStatus#CODECnet.minecraft.world.level.entity.PersistentEntitySectionManager#isTicking- 返回指定的区块当前是否正在Tick。net.minecraft.world.level.levelgen.Heightmap$Types#STREAM_CODECnet.minecraft.world.level.levelgen.featureAbstractHugeMushroomFeature#placeMushroomBlock- 在指定位置放置一个蘑菇方块,如果可以则替换方块。FallenTreeFeature- 一个生成带有给定长度树桩的倒伏树木的功能。TreeFeature#getLowestTrunkOrRootOfTree- 返回树装饰器的最低树干位置。
net.minecraft.world.level.levelgen.feature.configurations.FallenTreeConfiguration- 用于带有树桩的倒伏树的配置。net.minecraft.world.level.levelgen.feature.treedecoratorsAttachedToLogsDecorator- 一个装饰器,以一定的概率将随机方块附加到原木的给定方向。PlaceOnGroundDecorator- 一个装饰器,将树放置在有效的方块位置上。
net.minecraft.world.level.levelgen.structure.poolsListPoolElement#getElements- 返回结构池的元素。SinglePoolElement#getTemplateLocation- 返回元素使用的模板的位置。StructureTemplatePool#getTemplates- 返回一个带有权重的元素列表。
net.minecraft.world.level.levelgen.structure.structures.JigsawStructuregetStartPool- 返回要生成的拼图的起始池。getPoolAliases- 返回拼图使用的所有池。
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate#getDefaultJointType- 如果未指定或加载期间发生错误,返回两个拼图块之间的默认连接类型。net.minecraft.world.level.material.Fluid#getAABB、FluidState#getAABB- 返回流体的边界框。net.minecraft.world.scoresObjective#pack、$Packed- 处理目标数据的可序列化形式。PlayerTeam#pack、$Packed- 处理玩家队伍数据的可序列化形式。ScoreboardloadPlayerTeam、loadObjective- 从打包对象加载数据。$PackedScore- 处理记分板数据的可序列化形式。
net.minecraft.world.level.storage.loot.LootTable#KEY_CODECnet.minecraft.world.physAABB$Builder- 一个用于通过提供内部向量来构造边界框的构建器。Vec2#CODEC
net.minecraft.world.phys.shapes.CollisionContextplacementContext- 当从其物品放置方块时构造上下文。isPlacement- 返回上下文是否用于放置方块。
net.minecraft.world.ticks.TickPriority#CODEC
变更列表
net.minecraft.client.Screenshot现在是一个实用程序而不是实例类,意味着所有实例方法都已移除takeScreenshot(RenderTarget)->takeScreenshot(RenderTarget, Consumer<NativeImage>),不返回任何内容
net.minecraft.client.multiplayerClientChunkCache#replaceWithPacketData现在接受一个Map<Heightmap$Types, long[]>而不是CompoundTagMultiPlayerGameMode#hasInfiniteItems->net.minecraft.world.entity.LivingEntity#hasInfiniteMaterialsClientPacketListener#markMessageAsProcessed现在接受一个MessageSignature而不是PlayerChatMessage
net.minecraft.client.multiplayer.chat.ChatListener#handleChatMessageError现在接受一个可为 null 的MessageSignaturenet.minecraft.client.playerClientInput#leftImpulse、forwardImpulse->moveVector,现在是 protectedLocalPlayer#spinningEffectIntensity、oSpinningEffectIntensity->portalEffectIntensity、oPortalEffectIntensity
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$RenderSectiongetOrigin->getRenderOriginreset现在是公开的releaseBuffers已移除
$CompileTask#getOrigin->getRenderOrigin
net.minecraft.client.renderer.entityDonkeyRenderer现在接受一个DonekyRenderer$Type,包含纹理、模型层和装备信息ItemEntityRenderer#renderMultipleFromCount现在有一个接受模型边界框的重载UndeadHorseRenderer现在接受一个UndeadHorseRenderer$Type,包含纹理、模型层和装备信息
net.minecraft.client.renderer.entity.layersEquipmentLayerRenderer$TrimSpriteKey#textureId->spriteIdVillagerProfessionLayer#getHatData现在接受一个资源键到元数据部分的映射,并将注册表和值交换为一个持有者实例
net.minecraft.client.renderer.itemConditionalItemModel现在接受一个ItemModelPropertyTest而不是ConditionalItemModelPropertySelectItemModel现在接受一个$ModelSelector而不是一个对象映射
net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperty现在实现ItemModelPropertyTestItemModelPropertyTest持有之前在ConditionalItemModelProperty中的get方法
net.minecraft.commands.argumentsComponentArgumentERROR_INVALID_JSON->ERROR_INVALID_COMPONENTgetComponent->getRawComponent
ResourceKeyArgument#getRegistryKey现在是公开的StyleArgument#ERROR_INVALID_JSON->ERROR_INVALID_STYLE
net.minecraft.commands.arguments.itemComponentPredicateParser$Context#createComponentTest、createPredicateTest现在接受一个Dynamic而不是TagItemPredicateArgument$ComponentWrapper#decode现在接受一个Dynamic而不是RegistryOps、Tag对$PredicateWrapper#decode现在接受一个Dynamic而不是RegistryOps、Tag对
net.minecraft.coreBlockMathVANILLA_UV_TRANSFORM_LOCAL_TO_GLOBAL、VANILLA_UV_TRANSFORM_GLOBAL_TO_LOCAL现在是私有的getUVLockTransform->getFaceTransformation
Direction#rotate现在接受一个Matrix4fc而不是Matrix4fRotations现在是一个记录
net.minecraft.data.loot.BlockLootSubProvider#createPetalDrops->createSegmentedBlockDropsnet.minecraft.networkFriendlyByteBufwriteLongArray、readLongArray现在有静态委托,接受ByteBuf,并且*Fixed*版本用于固定大小的数组
ProtocolInfo$Unbound->$Details、net.minecraft.network.protocol.SimpleUnboundProtocol、net.minecraft.network.protocol.UnboundProtocol;不是一对一#bind->net.minecraft.network.protocol.SimpleUnboundProtocol#bind、UnboundProtocol#bind;不是一对一
SkipPacketException现在是一个接口,而不是EncoderException的子类
net.minecraft.network.chatComponentSerialization#flatCodec->flatRestrictedCodecLastSeenMessages$Update现在接受一个表示校验和值的字节LastSeenMessagesValidatorapplyOffset现在不返回任何内容,并且可以抛出$ValidationExceptionapplyUpdate现在返回原始消息,并且可以抛出$ValidationException
net.minecraft.network.codec.StreamCodec#composite现在有一个九个参数的重载net.minecraft.network.protocol.ProtocolInfoBuilder现在接受第三个泛型,表示如何修改提供的编解码器。addPacket现在有一个接受CodecModifier的重载build->buildUnbound,不是一对一protocol、serverboundProtocol、clientboundProtocol现在返回一个SimpleUnboundProtocol
net.minecraft.network.protocol.ConfigurationProtocols现在包含SimpleUnboundProtocol常量net.minecraft.network.protocol.gameClientboundContainerSetContentPacket现在是一个记录ClientboundMoveEntityPacket#getyRot、getxRot->getYRot、getXRotClientboundPlayerChatPacket现在接受一个聊天消息的全局索引ClientboundLevelChunkPacketdata#getHeightmaps现在返回一个Map<Heightmap.Types, long[]>ClientboundUpdateAdvancementsPacket现在接受一个布尔值,表示是否将进度显示为吐司GameProtocols常量现在是SimpleUnboundProtocol或UnboundProtocolServerboundContainerClickPacket现在是一个记录ServerboundMovePlayerPacket$Pos、$PosRot现在有一个接受Vec3作为位置的重载ServerboundSetStructureBlockPacket现在接受一个额外的布尔值,表示是否应在严格模式下生成结构
net.minecraft.network.protocol.handshake.HandshakeProtocols#SERVERBOUND_TEMPLATE现在是一个SimpleUnboundProtocolnet.minecraft.network.protocol.login.LoginProtocols#SERVERBOUND_TEMPLATE常量现在是SimpleUnboundProtocolnet.minecraft.network.protocol.status.StatusProtocols#SERVERBOUND_TEMPLATE常量现在是SimpleUnboundProtocolnet.minecraft.server.PlayerAdvancements#flushDirty现在接受一个布尔值,表示进度是否显示为吐司net.minecraft.server.bossevents.CustomBossEventsave->pack,不是一对一load现在接受 id 和打包变体以解包
net.minecraft.server.levelDistanceManagerhasPlayersNearby现在返回一个TriStateforEachBlockTickingChunks->forEachEntityTickingChunk,不是一对一
ServerEntity现在接受一个消费者,用于向所有玩家广播数据包,但忽略列表中的玩家除外ServerLevelgetForcedChunks->getForceLoadedChunksisPositionTickingWithEntitiesLoaded现在是公开的isNaturalSpawningAllowed->canSpawnEntitiesInChunk,BlockPos变体已移除
ServerPlayergetRespawnPosition、getRespawnAngle、getRespawnDimension、isRespawnForced->getRespawnConfig,不是一对一setRespawnPosition现在接受一个$RespawnConfig而不是单独的重生信息loadAndSpawnParentVehicle、loadAndSpawnEnderpearls现在接受一个CompoundTag,没有可选的包装
net.minecraft.server.network.ServerGamePacketListenerImpl现在实现GameProtocols$Contextnet.minecraft.sounds.SoundEvents有以下声音现在是Holder包装的:ITEM_BREAKSHIELD_BLOCK、SHIELD_BREAK、WOLF_ARMOR_BREAK
net.minecraft.utilBrightnessFULL_BRIGHT现在是 finalpack现在有一个静态重载,接受块光和天空光。
ExtraCodecs#MATRIX4f现在是一个Codec<Matrix4fc>Util#makeEnumMap返回Map超实例而不是具体的EnumMap
net.minecraft.util.parsing.packrat.commands.TagParseRule现在接受一个标签类型的泛型- 构造函数现在是公开的,接受一个
DynamicOps
- 构造函数现在是公开的,接受一个
net.minecraft.util.profilingActiveProfiler现在接受一个BooleanSupplier而不是一个布尔值ContinuousProfiler现在接受一个BooleanSupplier而不是一个布尔值
net.minecraft.util.worldupdate.WorldUpgrader现在接受当前的WorldDatanet.minecraft.worldBossEvent$BossBarColor、$BossBarOverlay现在实现StringRepresentableContainer现在实现Iterable<ItemStack>
net.minecraft.world.effectMobEffectgetBlendDurationTicks->getBlendInDurationTicks、getBlendOutDurationTicks、getBlendOutAdvanceTicks;不是一对一setBlendDuration现在有一个接受三个整数来设置淡入、淡出和淡出提前刻的重载
MobEffectInstance#tick->tickServer、tickClient;不是一对一
net.minecraft.world.entityEntitycancelLerp->InterpolationHandler#cancellerpTo->moveOrInterpolateTolerpTargetX、lerpTargetY、lerpTargetZ、lerpTargetXRot、lerpTargetYRot->getInterpolationonAboveBubbleCol->onAboveBubbleColumn现在接受一个BlockPos作为气泡柱粒子的生成位置- 逻辑委托给受保护的静态
handleOnAboveBubbleColumn
- 逻辑委托给受保护的静态
isControlledByOrIsLocalPlayer->isLocalInstanceAuthoritative,现在是 finalisControlledByLocalInstance->isLocalClientAuthoritative,现在是 protectedisControlledByClient->isClientAuthoritativefallDistance、causeFallDamage现在是 doubleabsMoveto->absSnapToabsRotateTo->asbSnapRotationTomoveTo->snapTosendBubbleColumnParticles现在是静态的,接受LevelonInsideBubbleColumn逻辑委托给受保护的静态handleOnInsideBubbleColumn
EntityTypePOTION->SPLASH_POTION、LINGERING_POTION,不是一对一$EntityFactory#create现在可以返回一个 null 实例
ExperienceOrb#value->DATA_VALUEItemBasedSteering不再接受用于判断是否有马鞍的访问器LivingEntitylastHurtByPlayerTime->lastHurtByPlayerMemoryTimelerpSteps、lerpX、lerpY、lerpZ、lerpYRot、lerpXRot->interpolation,不是一对一isAffectedByFluids现在是公开的removeEffectNoUpdate现在是 finaltickHeadTurn现在不返回任何内容canDisableShield->canDisableBlocking,现在通过WEAPON数据组件设置calculateFallDamage现在接受 double 而不是 float
MobhandDropChances、armorDropChances、bodyArmorDropChance->dropChances,不是一对一getEquipmentDropChance->getDropChances,不是一对一
net.minecraft.world.entity.ai.Brain#addActivityWithConditions现在有一个接受整数表示起始优先级的重载net.minecraft.world.entity.ai.behaviorLongJumpToRandomPos$PossibleJump现在是一个记录VillagerGoalPackages#get*Package现在接受一个持有者包装的职业
net.minecraft.world.entity.ai.gossip.GossipContainer#store、update->clear、putAll、copy;不是一对一net.minecraft.world.entity.animalPig现在是一个VariantHolderSheep->.sheep.SheepWaterAnimal#handleAirSupply现在接受一个ServerLevel
net.minecraft.world.entity.animal.axolotl.Axolotl#handleAirSupply现在接受一个ServerLevelnet.minecraft.world.entity.monster.ZombieVillager#setGossips现在接受一个GossipContainernet.minecraft.world.entity.monster.warden.WardenSpawnTracker现在有一个重载,将初始参数设置为零net.minecraft.world.entity.npcVillager现在接受一个键或一个VillagerType的持有者setGossips现在接受一个GossipContainer
VillagerData现在是一个记录set*->with*
VillagerProfession现在接受一个Component作为名称VillagerTradesTRADES现在接受一个资源键作为映射的键- 这对于所有其他特定类型的交易类似
$FailureItemListing现在是私有的
net.minecraft.world.entity.player.PlayerstopFallFlying->LivingEntity#stopFallFlyingisSpectator、isCreative在Player类中不再是抽象的
net.minecraft.world.entity.projectile.ThrownPotion->AbstractThrownPotion,在ThrownLingeringPotion和ThrownSplashPotion中实现net.minecraft.world.entity.raid.Raid(int, ServerLevel, BlockPos)->Raid(BlockPos, Difficulty)tick、addWaveMob现在接受ServerLevel
net.minecraft.world.entity.vehicleAbstractMinecart#setDisplayBlockState->setCustomDisplayBlockStateMinecartBehaviorcancelLerp->InterpolationHandler#cancellerpTargetX、lerpTargetY、lerpTargetZ、lerpTargetXRot、lerpTargetYRot->getInterpolation
MinecartTNT#primeFuse现在接受DamageSource原因
net.minecraft.world.inventoryAbstractContainerMenusetRemoteSlotNoCopy->setRemoteSlotUnsafe,不是一对一setRemoteCarried现在接受一个HashedStack
ClickType现在接受一个表示其表示的 idContainerSynchronizer#sendInitialData现在接受一个堆栈列表而不是NonNullList
net.minecraft.world.itemEitherHolder现在接受一个Either实例而不是仅仅一个可选的持有者和ResourceKeyItemcanAttackBlock->canDestroyBlockhurtEnemy不再返回任何内容onCraftedBy不再接受一个单独的Level实例,现在依赖于Player提供的实例
ItemStackvalidateStrict现在是公开的onCraftedBy不再接受一个单独的Level实例,现在依赖于Player提供的实例
MapItemcreate现在接受一个ServerLevel而不是LevellockMap现在是私有的
ThrowablePotionItem现在是抽象的,包含两个创建AbstractThrownPotion实体的方法WrittenBookItem#resolveBookComponents->WrittenBookContent#resolveForItem
net.minecraft.world.item.alchemy.PotionContents现在实现TooltipProviderforEachEffect、applyToLivingEntity现在接受一个 float 表示持续时间的标量
net.minecraft.world.item.component.WrittenBookContent现在实现TooltipProvidernet.minecraft.world.item.craftingSmithingRecipe#baseIngredient现在返回一个IngredientSmithingTransformRecipe现在接受一个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.levelBlockGetter#boxTraverseBlocks->forEachBlockIntersectedBetween,不是一对一CustomSpawner#tick不再返回任何内容GameRules$Type现在接受一个值类LevelonBlockStateChange->updatePOIOnBlockStateChangeisDay->isBrightOutsideisNight->isDarkOutsidesetMapData->net.minecraft.server.level.ServerLevel#setMapDatagetFreeMapId->net.minecraft.server.level.ServerLevel#getFreeMapId
LevelAccessor#blockUpdated->updateNeighborsAt
net.minecraft.world.level.biome.MobSpawnSettings$SpawnerData现在是一个记录net.minecraft.world.level.blockAttachedStemBlock现在继承VegetationBlockAzaleaBlock现在继承VegetationBlockBlock#fallOn现在接受一个 double 作为坠落伤害,而不是 floatBushBlock现在继承VegetationBlock并实现BonemealableBlockColoredFallingBlock#dustColor现在是 protectedCropBlock现在继承VegetationBlockDeadBushBlock->DryVegetationBlockDoublePlantBlock现在继承VegetationBlockFallingBlock#getDustColor现在是抽象的FlowerBedBlock现在继承VegetationBlockFlowerBlock现在继承VegetationBlockFungusBlock现在继承VegetationBlockLeafLitterBlock现在继承VegetationBlockLeavesBlock现在是抽象的,接受粒子生成的概率- 粒子通过
spawnFallingLeavesParticle生成
- 粒子通过
MangroveLeavesBlock现在继承TintedParticleLeavesBlockMushroomBlock现在继承VegetationBlockNetherSproutsBlock现在继承VegetationBlockNetherWartBlock现在继承VegetationBlockParticleLeavesBlock->LeafLitterBlockPinkPetalsBlock->FlowerBedBlockRootsBlock现在继承VegetationBlockRotation现在有一个用于网络同步的索引SaplingBlock现在继承VegetationBlockSeagrassBlock现在继承VegetationBlockSeaPickleBlock现在继承VegetationBlockStemBlock现在继承VegetationBlockSweetBerryBushBlock现在继承VegetationBlockTallGrassBlock现在继承VegetationBlockTntBlock#prime现在返回是否生成了点燃的 TNT。WaterlilyBlock现在继承VegetationBlock
net.minecraft.world.level.block.entityBlockEntityparseCustomNameSafe现在接受一个可为 null 的Tag而不是字符串getPosFromTag现在接受ChunkPos$ComponentHolder#COMPONENTS_CODEC现在是一个MapCodec
BLockEntityType#create不再是可为 null 的
net.minecraft.world.level.block.entity.trialspawner.TrialSpawner#codec现在返回一个MapCodecnet.minecraft.world.level.block.state.StateHoldergetNullableValue现在是私有的hasProperty不再包含泛型
net.minecraft.world.level.chunkChunkAccess#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_FREQUENCYnet.minecraft.world.level.levelgen.feature.TreeFeature#isVine现在是公开的net.minecraft.world.level.levelgen.structure.pools.aliasDirect->DirectPoolAliasRandom->RandomPoolAliasRandomGroup->RandomGroupPoolAlias
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate$JigsawBlockInfo现在接受StructureTemplatePool的ResourceKey而不是原始ResourceLocationnet.minecraft.world.level.saveddata.maps.MapFrame现在是一个记录save、load->CODEC,不是一对一
net.minecraft.world.level.storage.loot.functions.SetWrittenBookPagesFunction#PAGE_CODEC->WrittenBookContent#PAGES_CODECnet.minecraft.world.scoresScore#write->CODEC,不是一对一ScoreboardsavePlayerScores->packPlayerScores,不是一对一loadPlayerScores->loadPlayerScore,不是一对一
Team$CollisionRule、$Visibility现在是StringRepresentable
net.minecraft.world.phys.shapes.EntityCollisionContext现在接受一个布尔值,表示是否用于放置方块net.minecraft.world.ticks.SavedTickloadTick、saveTick、save->codec,不是一对一loadTickList->filterTickListForChunk,不是一对一
移除列表
com.mojang.blaze3d.vertex.BufferUploadernet.minecraft.core.Rotations#getWrapped*net.minecraft.network.chat.ComponentSerialization#FLAT_CODECnet.minecraft.network.protocol.gameClientboundAddExperimentOrbPacketClientGamePacketListener#handleAddExperienceOrb
net.minecraft.resources.ResourceLocation$Serializernet.minecraft.server.network.ServerGamePacketListenerImpl#addPendingMessagenet.minecraft.worldBossEvent$BossBarColor#byName、$BossBarOverlay#byNameClearable#tryClear
net.minecraft.world.effect.MobEffectInstance#save、loadnet.minecraft.world.entityEntityisInBubbleColumnisInWaterRainOrBubble、isInWaterOrBubblenewDoubleList、newFloatListrecordMovementThroughBlocks
EntityEvent#ATTACK_BLOCKED、SHIELD_DISABLEDItemBasedSteeringaddAdditionalSaveData、readAdditionalSaveDatasetSaddle、hasSadddle
LivingEntitytimeOffs、rotOffsrotAoRun、runanimStep、animStep0appliedScalecanBeNameTagged
MobDEFAULT_EQUIPMENT_DROP_CHANCEPRESERVE_ITEM_DROP_CHANCE_THRESHOLD、PRESERVE_ITEM_DROP_CHANCE
NeutralMob#setLastHurtByPlayerPositionMoveRotation#ofEntityUsingLerpTarget
net.minecraft.world.entity.ai.attributes.AttributeModifier#save、loadnet.minecraft.world.entity.animalDolphin#setTreasurePos、getTreasurePosFox$Variant#byNameMushroomCow$Variant#byNamePanda$Gene#byNameSalmon$Variant#byNameTurtlegetHomePossetTravelPos、getTravelPosisGoingHome、setGoingHomeisTravelling、setTravelling
net.minecraft.world.entity.animal.armadillo.Armadillo$ArmadilloState#fromNamenet.minecraft.world.entity.npc.VillagerTrades#EXPERIMENTAL_WANDERING_TRADER_TRADESnet.minecraft.world.entity.projectile.AbstractArrow#getBaseDamagenet.minecraft.world.entity.raid.RaidgetLevel、getIdsave
net.minecraft.world.entity.vehicle.AbstractMinecart#hasCustomDisplay、setCustomDisplaynet.minecraft.world.item.ItemStack#parseOptional、saveOptionalnet.minecraft.world.item.equipment.trim.TrimPattern#templateItemnet.minecraft.world.level.Level#updateNeighborsAt(BlockPos, Block)net.minecraft.world.level.block.entityCampfireBlockEntity#dowsePotDecorations#save、load
net.minecraft.world.level.levelgen.BelowZeroRetrogen#readnet.minecraft.world.level.levelgen.structure.structures.RuinedPortalPiece$VerticalPlacement#byNamenet.minecraft.world.level.saveddata.maps.MapBanner#LIST_CODECnet.minecraft.world.scores.Team$CollisionRule#byName$Visibility#getAllNames、byName
net.minecraft.world.ticks.LevelChunkTicks#save、load
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#render、AbstractContainerScreen#renderBg 等)。这些方法现在不再实际渲染组件,而是将它们提交给 GuiRenderState 以存储在“渲染”阶段使用。GuiRenderState 存储在 GameRenderer 上,并传递给 GuiGraphics,后者使用前述方法将所需对象添加到渲染状态。
渲染阶段实际处理所有对象的渲染。这是通过 GuiRenderer 处理的,它从 GuiRenderState 读取数据,并在经过一些委托的准备和排序后,将对象渲染到屏幕上。GuiRenderer 也存储在 GameRenderer 上。
元素排序
现在,元素是如何渲染到屏幕上的?在之前的版本中,这主要基于渲染调用的顺序。然而,新系统使用两种不同的排序方法。第一种方法使用层和线性树来处理深度。第二种方法基于三个因素(按优先级顺序)使用比较器:ScreenRectangle 剪裁、RenderPipeline 顺序和 TextureSetup 的哈希码。这些都存储在通过 GuiRenderState#submitGuiElement 传递给 GuiRenderState 的 GuiElementRenderState 上。
一旦元素排序完毕,它们将从 Z 值为 0 开始渲染,每个元素比前一个元素向前渲染 0.01。
作为警告,由于元素排序顺序,某些自定义配置可能导致屏幕渲染不正确。因此,您必须理解这些方法及其分配的值在排序元素时的工作原理。
层与树
第一种排序方法处理对象渲染的 z 深度。
首先从线性树开始。顾名思义,它基本上是一个双向链接的 GuiRenderState$Node 列表。每个节点包含自己的要渲染的元素列表。使用 GuiRenderState#up 或 down 来导航节点列表,每个方法要么获取下一个节点,要么如果不存在则创建一个新节点。给定树中的节点从底部到顶部渲染,这意味着 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 定义了在渲染管线中使用的 Sampler0、Sampler1 和 Sampler2,通过 GuiElementRenderState#textureSetup 存储。没有纹理的元素将首先排序,然后是记录对象的 getSortKey。注意,目前这返回 TextureSetup 的 hashCode,由于 GpuTextureView 不实现 hashCode,而是依赖于身份对象哈希,这可能是不确定的。
GuiElementRenderState
现在我们理解了排序,我们一直在使用的 GuiElementRenderState 到底是什么?实际上,渲染到屏幕的每个对象都由一个 GuiElementRenderState 表示,从库存菜单中看到的玩家到每个单独的物品。一个 GuiElementRenderState 定义了四个方法。首先,是用于排序以及如何渲染到屏幕的常用方法(pipeline、scissorArea、textureSetup、bounds)。然后是 buildVertices,它接受 VertexConsumer 来写入顶点和 z 深度。对于 GUI,这通常调用 VertexConsumer#addVertexWith2DPose。
原版提供了三种类型的 GuiElementRenderState:BlitRenderState、ColoredRectangleRenderState、GlyphEffectRenderState 和 GlyphRenderState。ColoredRectangleRenderState 和 GlyphRenderState/GlyphEffectRenderState 分别是处理基本颜色矩形和文本字符的简单情况。BlitRenderState 覆盖所有其他情况,因为几乎所有方法最终都会写入一个 GpuTexture,然后由它消费。
GuiElementRenderState 通过 GuiRenderState$Node#submitGuiElement 添加到 GuiRenderState。GuiRenderState 使 submitBlitToCurrentLayer 和 submitGlyphToCurrentLayer 可用于添加纹理和字形。例如,这些由 GuiGraphics#*line、fill 和 blit* 方法调用。
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 是一个特殊情况,用于将文本渲染到屏幕。它接受 Font、FormattedCharSequence、当前姿势、其 XY 坐标、颜色、背景颜色、是否有阴影及其渲染边界。
就在“渲染”阶段之前,GuiRenderer 将 GuiTextRenderState 转换为 GuiElementRenderState,更具体地说是 GlyphRenderState 或 GlyphEffectRenderState,具体取决于通过 GuiTextRenderState#ensurePrepared 应渲染的内容。这执行与物品渲染状态类似的过程,其中文本被写入 GpuTexture 以供消费。任何背景首先被渲染,然后是背景效果,然后是字符,最后是前景效果。
GuiElementRenderState 通过 GuiRenderState#submitText 添加到 GuiRenderState。这由 GuiGraphics#draw*String 和 render*Tooltip 方法调用。
画中画
画中画是一个特殊情况,用于将任意对象渲染到 GpuTexture,然后传递给 BlitRenderState。画中画由两个组件组成:PictureInPictureRenderState 和 PictureInPictureRenderer。
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。
DialogBody 和 InputControl 只是没有定义结构的通用接口。实现它们,或者任何对话框,都需要在客户端和服务器上向可用类型进行一些注册。
自定义主体
一个 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。
一个自定义动作包含两个方法:一个返回在编码期间使用的 MapCodec(codec),另一个根据输入字符串到其 $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,给定父 Screen、Dialog 实例和用于与服务器通信的 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.guiFontdrawInBatch不再返回任何内容prepareText- 准备要渲染到屏幕的文本。splitIgnoringLanguage- 按提供的顺序拆分文本,而不经过语言处理程序处理。ALPHA_CUTOFF已移除$GlyphVisitor- 一个处理要渲染的字形或效果的接口。$PreparedText- 一个接口,通过访问每个字形来定义应如何渲染一段文本。$StringRenderOutput->$PreparedTextBuilder,不再接受MultiBufferSource、Matrix4f、$DisplayMode、打包的光照坐标和逆深度布尔值
GuishouldRenderDebugCrosshair- 如果应渲染调试准星,则返回 true。$RenderFunction- 一个接口,定义如何在 GUI 上渲染某个部分或元素。
GuiGraphics现在接受一个GuiRenderState而不是MultiBufferSource$BufferSourceMAX_GUI_Z、MIN_GUI_Z已移除pose现在返回一个Matrix3x2fStackflush已移除nextStratum- 添加另一个层,用于遍历在先前树中的所有节点之后渲染。- 所有方法不再接受
RenderType、VertexConsumer或Function<ResourceLocation, RenderType>,而是根据调用指定RenderPipeline和TextureSetup drawString、drawStringWithBackdrop不再返回任何内容draw*String方法现在必须传入一个 ARGB 值,其中 A 不能为 0。renderItem(ItemStack, int, int, int, int)已移除drawSpecial已移除,根据特殊情况由单独的submit*RenderState取代blurBeforeThisStratum- 通知渲染状态,模糊效果应在该层和所有先前渲染的层之间渲染。每帧只能应用一次。render*Tooltip->set*TooltipForNextFrame,不直接添加到渲染状态,而是在不存在或被覆盖时等待调用renderDeferredTooltiprenderDeferredTooltip- 添加要在新层上渲染的工具提示信息。blitSprite现在有一个接受浮点 R 色调颜色的重载$ScissorStack#peek- 获取堆栈上的最后一个矩形。
LayeredDraw类已移除
net.minecraft.client.gui.componentsAbstractTextAreaWidget现在有一个重载,接受两个额外的布尔值,表示是否显示背景或装饰AbstractWidget#getTooltip已移除CycleButton$Builder#displayOnlyValue现在有一个接受boolean设置的重载EditBoxsetCentered- 设置文本位置是否应居中。setTextShadow- 设置文本是否应有阴影效果。
FocusableTextWidget现在可以接受一个布尔值,表示是否填充背景DEFAULT_PADDING现在是公开的
ImageWidget#updateResource- 更新组件上图像的精灵。ItemDisplayWidget- 一个显示ItemStack的小部件。LogoRenderer#keepLogoThroughFade- 当为 true 时,即使标题屏幕淡出,也保持徽标可见。MultiLineEditBox现在是包私有的,应通过builder构造,调用$Builder#set*方法setLineLimit- 设置文本字段的行限制。setValue现在有一个接受boolean的重载,用于确定是否应强制通过最大行限制
MultiLineLabelgetStyleAtCentered- 计算居中文本的组件样式。getStyleAtLeftAligned- 计算左对齐文本的组件样式。
MultilineTextField#NO_CHARACTER_LIMIT->NO_LIMITsetLineLimit- 设置文本字段上可以写入的最大行数。hasLineLimit- 返回文本字段是否有行限制。setValue现在有一个接受boolean的重载,用于确定是否应强制通过最大行限制
MultiLineTextWidget#configureStyleHandling- 设置在悬停组件时是否显示某些内容以及点击时的操作。ScrollableLayout- 一个具有某些定义边界并且可以滚动的布局。SplashRenderer#render现在接受一个浮点数作为 R 颜色,而不是 intWidgetTooltipHolder#refreshTooltipForNextRenderPass现在接受GuiGraphics和 XY 位置
net.minecraft.client.gui.components.spectator.SpectatorGui#renderTooltip->renderActionnet.minecraft.client.gui.components.tabsLoadingTab- 一个表示当前正在加载信息的标签页。Tab#getTabExtraNarration- 返回标签页的提示旁白。TabManager现在可以接受两个Consumer,用于在选中或取消选中标签页时执行的操作TabNavigationBargetTabs- 返回导航栏上的标签页列表。setTabActiveState- 设置给定标签页索引的活动状态。setTabTooltip- 设置给定标签页索引的工具提示信息。
net.minecraft.client.gui.components.toastsNowPlayingToast- 一个显示当前正在播放的背景音乐的吐司。ToastxPos、yPos- 获取相对于当前吐司索引的 x 和 y 位置。onFinishedRendering- 吐司在屏幕上完成渲染后调用的方法。
ToastManager现在接受OptionsshowNowPlayingToast、hideNowPlayingToast、createNowPlayingToast、removeNowPlayingToast- 处理“正在播放”音乐吐司。$ToastInstance#resetToast- 重置吐司。
net.minecraft.client.gui.contextualbarContextualBarRenderer- 一个接口,定义了一个具有某些要渲染的背景的对象。ExperienceBarRenderer- 绘制经验条。JumpableVehicleBarRenderer- 绘制跳跃力量条(例如,马跳跃)。LocatorBarRenderer- 绘制指向给定路径点的条。
net.minecraft.client.gui.font.GlyphRenderTypes现在接受一个用于 GUI 渲染的RenderPipelinenet.minecraft.client.gui.font.glyphs.BakedGlyph现在接受一个GpuTextureViewextractEffect- 提取一个字形效果(例如阴影)并提交要渲染的元素。extractBackground- 提取一个字形效果并提交要在背景 Z 上渲染的元素。left、top、right、bottom- 计算字形的边界。textureView- 返回构成字形的纹理视图。guiPipeline- 返回渲染字形的管线。renderChar、renderEffect现在接受一个额外的布尔值,当为 true 时将 Z 偏移设置为0,为 false 时设置为0.001$Effect#left、top、right、bottom- 计算字形效果的边界。$GlyphInstance#left、top、right、bottom- 计算字形实例的边界。
net.minecraft.client.gui.navigation.ScreenRectangletransformAxisAligned现在接受Matrix3x2f而不是Matrix4fintersects- 返回此矩形是否与另一个矩形重叠。encompasses- 返回此矩形是否完全包含另一个矩形。transformMaxBounds- 返回一个新矩形,该矩形通过提供的矩阵移动到给定位置。
net.minecraft.client.gui.renderGuiRenderer- 一个将所有提交的元素渲染到屏幕的类。TextureSetup- 一个记录,指定在渲染管线中使用的采样器 0-2。前两个纹理视图是任意的,第三个用于当前的光照图纹理。
net.minecraft.client.gui.render.pipGuiBannerResultRenderer- 旗帜结果预览的渲染器。GuiBookModelRenderer- 附魔屏幕中书模型的渲染器。GuiEntityRenderer- 给定实体的渲染器。GuiProfilerChartRenderer- 分析器图表的渲染器。GuiSignRenderer- 编辑屏幕中告示牌背景的渲染器。GuiSkinRenderer- 具有给定皮肤的玩家的渲染器。OversizedItemRenderer- 用于物品模型应渲染得比其物品槽位大时的渲染器。PictureInPictureRenderer- 一个抽象类,用于渲染非标准 2D 元素、物品或文本的动态元素。
net.minecraft.client.gui.render.stateBlitRenderState- 用于基本 2D 纹理 blit 的元素状态。ColoredRectangleRenderState- 用于带有色调的简单矩形的元素状态。GlyphEffectRenderState- 用于字形效果(例如,字体文本阴影)的元素状态。GlyphRenderState- 用于字形(字体文本)的元素状态。GuiElementRenderState- 一个表示要渲染的元素状态的接口。GuiItemRenderState- 一个表示要渲染的物品状态的记录。GuiRenderState- 要渲染到屏幕的 GUI 的状态。GuiTextRenderState- 一个表示文本及其渲染位置的记录。ScreenArea- 一个定义元素渲染区域的接口。这不会影响剪裁,而是影响层顺序。
net.minecraft.client.gui.render.state.pipGuiBannerResultRenderState- 旗帜结果预览的状态。GuiBookModelRenderState- 附魔屏幕中书模型的状态。GuiEntityRenderState- 给定实体的状态。GuiProfilerChartRenderState- 分析器图表的状态。GuiSignRenderState- 编辑屏幕中告示牌背景的状态。GuiSkinRenderState- 具有给定皮肤的玩家的状态。OversizedItemRenderState- 可以以任意大小渲染的物品模型的状态。PictureInPictureRenderState- 一个定义将画中画渲染到屏幕所需基本状态的接口。
net.minecraft.client.gui.screensConfirmScreenlayout- 定义一个由八个单位间隔的垂直元素列表。yesButton、noButton->yesButtonComponent、noButtonComponentyesButton、noButton现在表示实际的按钮
addAdditionalText- 在布局中的按钮之前添加任何附加文本。addButtons- 在布局中添加按钮。
PauseScreenrendersNowPlayingToast- 返回是否应渲染“正在播放”吐司。onDisconnect->disconnectFromWorld,现在是公开和静态的;不是一对一
ScreenCUBE_MAP->net.minecraft.client.renderer.GameRenderer#cubeMapPANORAMA->net.minecraft.client.renderer.GameRenderer#panoramarenderBlurredBackground现在接受GuiGraphics*TooltipForNextRenderPass方法要么已移除,要么移至GuiGraphicsFADE_IN_TIME- 表示某个元素淡入需要多少毫秒。fadeWidgets- 设置作为屏幕子级添加的AbstractWidget的 alpha 值。handleClickEvent- 处理点击组件时要播放的事件。defaultHandleClickEvent- 点击组件时要执行的默认逻辑。clickUrlAction- 点击 URL 时要执行的逻辑(具有打开 URL 样式)。clickCommandAction- 应执行命令时要执行的逻辑(具有 * 命令样式)。
net.minecraft.client.gui.screens.dialogButtonListDialogScreen- 一个包含一些按钮列表的对话框屏幕。DialogConnectionAccess- 一个处理来自对话框的通用交互信息的客户端接口。DialogControlSet- 对话框屏幕的输入处理程序。DialogListDialogScreen- 一个指向其他对话框的按钮列表的DialogListDialog。DialogScreen- 某个对话框模态的屏幕。DialogScreens- 对话框模态到其关联屏幕的工厂注册表。MultiButtonDialogScreen- 一个MultiActionDialog的按钮列表。ServerLinksDialogScreen- 一个ServerLinksDialog的按钮列表。SimpleDialogScreen- 某个简单对话框的对话框屏幕。WaitingForResponseScreen- 处理客户端/服务器之间对话框提交的停机时间的屏幕。
net.minecraft.client.gui.screens.dialog.bodyDialogBodyHandler- 描述标题和动作/输入之间内容的主体元素列表。DialogBodyHandlers-DialogBody到其DialogBodyHandler的注册表。
net.minecraft.client.gui.screens.dialog.inputInputControlHandler- 用户输入处理程序。InputControlHandlers-InputControl到其InputControlHandler的注册表。
net.minecraft.client.gui.screens.inventoryAbstractContainerScreenSLOT_ITEM_BLIT_OFFSET已移除renderContents- 渲染库存的槽位和标签。renderCarriedItem- 渲染持有的物品。renderSnapbackItem- 渲染与持有物品交换的物品。$SnapbackData- 保存关于拖拽或交换物品从持有位置移动到其槽位位置的信息。
AbstractSignEditScreen#offsetSign->getSignYOffset,不是一对一BookEditScreenTEXT_*、IMAGE_*、BACKGROUND_TEXTURE_*现在是公开的
BookSignScreen- 用于签署书的屏幕。BookViewScreencloseScreen->closeContainerOnServer,不是一对一$BookAccess#getPage现在返回一个Component
EffectsInInventoryrenderEffects现在是公开的renderTooltip已被重载为一个公共方法
InventoryScreen#renderEntityInInventory不再接受 XY 偏移,而是接受 4 个int来表示要渲染到的区域ItemCombinerScreen#renderFg已移除
net.minecraft.client.gui.screens.inventory.tooltipClientTooltipComponent#renderText不再接受姿势和缓冲区,而是接受GuiGraphics来提交要渲染的文本TooltipRenderUtil#renderTooltipBackground不再接受 Z 偏移
net.minecraft.client.gui.screens.multiplayer.ServerLinksScreen类已移除,被对话框模态取代net.minecraft.client.gui.screens.socialPlayerEntry#refreshHasDraftReport- 设置当前上下文是否具有针对此玩家的报告。SocialInteractionsPlayerList#refreshHasDraftReport- 刷新当前上下文是否对所有玩家有报告。
net.minecraft.client.gui.screens.worldselection.ExperimentsScreen$ScrollArea类已移除,被ScrollableLayout取代net.minecraft.client.model.geom.ModelPart#getExtentsForGui- 获取表示已变换到适当空间的部件的向量集。net.minecraft.client.multiplayer.ClientCommonPacketListenerImplshowDialog- 显示当前对话框,动态创建屏幕。serverLinks- 返回客户端可以访问的服务器链接条目。createDialogAccess- 创建用于通信的客户端对话框处理程序。clearDialog- 关闭当前对话框屏幕。
net.minecraft.client.player.LocalPlayer#experienceDisplayStartTick- 表示经验显示应被优先考虑的开始刻。net.minecraft.client.rendererGameRenderer不再接受ResourceManagerITEM_ACTIVATION_ANIMATION_LENGTH已移除setRenderHand已移除renderZoomed已移除getPanorama- 返回全景渲染器。
LightTexture#getTexture->getTextureView,不是一对一MapRenderer#WIDTH、HEIGHT现在是公开的PanoramaRenderer#registerTextures- 注册纹理以供立方体贴图使用。PostPass$Input#texture现在返回GpuTextureView而不是GpuTextureRenderPipelinesGUI_OVERLAY、GUI_GHOST_RECIPE_OVERLAY、GUI_TEXTURED_OVERLAY已移除GUI_TEXTURED_PREMULTIPLIED_ALPHA- 一个假设纹理在合成阶段已经预乘了透明度的管线。
RenderStateShard$Builder#add不再接受是否应模糊着色器$TextureStateShard不再接受设置模糊模式的TriState
RenderTypedebugLine已移除gui、guiOverlay、guiTexturedOverlay、guiOpaqueTexturedBackground、guiNauseaOverlay、guiTextHighlight、guiGhostRecipeOverlay、guiTextured已移除vignette已移除crosshair已移除mojangLogo已移除
ScreenEffectRenderer现在是一个实例实现,而不是仅仅一个静态方法- 构造函数接受当前的
Minecraft实例和一个MultiBufferSource renderScreenEffect现在是一个实例方法,接受实体是否在睡觉以及部分刻resetItemActivation、displayItemActivation- 处理物品自动激活时的情况(例如,图腾)。
- 构造函数接受当前的
net.minecraft.client.renderer.blockentity*Renderer#getExtents- 将所有模型表示的变换后的向量添加到一个集合中。HangingSignRendererMODEL_RENDER_SCALE现在是公开的translateBase现在是公开的
SignRendererRENDER_SCALE现在是公开的applyInHandTransforms- 变换堆栈以正确表示所持告示牌的位置。
SkullBlockRenderer#getRenderType(SkullBlock$Type, ResolvableProfile, ResourceLocation)->getSkullRenderType、getPlayerSkinRenderType;不是一对一
net.minecraft.client.renderer.entity.ItemRendererGUI_SLOT_CENTER_X、GUI_SLOT_CENTER_Y、ITEM_DECORATION_BLIT_OFFSET已移除COMPASS_*->SPECIAL_*
net.minecraft.client.renderer.itemClientItem$Properties#oversizedInGui- 当为 true 时,允许物品在 GUI 中渲染到 16x16 框之外;否则,将大小裁剪到框内。ItemStackRenderStatesetAnimated、isAnimated- 返回物品是否有动画(例如,闪光)。appendModelIdentityElement、getModelIdentity、clearModelIdentity- 处理正在渲染的标识组件。getModelBoundingBox- 计算模型的边界框。setOversizedInGui、isOversizedInGui- 处理物品何时可以根据其属性在 GUI 中过大。
net.minecraft.client.renderer.specialPlayerHeadSpecialRenderer- 根据其渲染信息渲染玩家头颅。SkullSpecialRenderer现在实现NoDataSpecialModelRenderer,不再接受模型或纹理覆盖,而是接受要使用的RenderTypeSpecialModelRenderer#getExtents- 将表示此渲染器使用的所有模型的变换向量添加到一个集合中。
net.minecraft.client.renderer.texture.TextureAtlasSprite#isAnimated- 返回精灵是否有任何动画。net.minecraft.commands.arguments.ResourceOrIdArgument#dialog、getDialog、$DialogArgument- 处理对话框屏幕的命令参数。net.minecraft.core.registriesBuiltInRegistries#DIALOG_TYPE、DIALOG_ACTION_TYPE、INPUT_CONTROL_TYPE、DIALOG_BODY_TYPERegistries#DIALOG_TYPE、DIALOG_ACTION_TYPE、INPUT_CONTROL_TYPE、DIALOG_BODY_TYPE、DIALOG
net.minecraft.data.tags.DialogTagsProvider- 对话框的标签提供者。net.minecraft.network.chatClientEvent$Action#SHOW_DIALOG、CUSTOMvalueCodec- 返回用于编码此动作的映射编解码器。
$Custom- 一个包含一些要发送到服务器的 nbt 有效负载的事件,目前什么都不做。$ShowDialog- 一个显示指定对话框的事件。
CommonComponentsGUI_RETURN_TO_MENU- 显示“返回菜单”文本的组件。disconnectButtonLabel- 根据服务器是否是本地服务器返回组件。
net.minecraft.network.protocol.commonClientboundClearDialogPacket- 关闭当前对话框屏幕。ClientboundShowDialogPacket- 打开一个新的对话框屏幕。ServerboundCustomClickActionPacket- 向服务器发送一个自定义动作。
net.minecraft.server.dialogActionButton- 一个可以在点击时执行某些Action的按钮。ButtonListDialog- 一个具有若干列可点击按钮的对话框模态。CommonButtonData- 与对话框模态中每个按钮关联的数据。CommonDialogData- 与每个对话框模态关联的数据。ConfirmationDialog- 一个可以选择是或否的对话框模态。Dialog- 定义某个对话框模态的基础接口。DialogAction- 通常在点击某个动作按钮后执行的动作。DialogListDialog- 一个指向其他对话框的按钮的可滚动列表。Dialogs- 一个注册Dialog的数据包引导程序。DialogTypes- 用于编码某个对话框模型的映射编解码器注册表。Input- 一个将某个键映射到InputControl的处理程序。MultiActionDialog- 一个按列排列的动作的可滚动列表。NoticeDialog- 一个在页脚中只有一个动作的简单屏幕。ServerLinksDialog- 一个从服务器接收的链接的可滚动列表,按列排列。SimpleDialog- 一个定义可以采取的主要动作的对话框。
net.minecraft.server.dialog.actionAction- 对某些输入执行的通用操作,通常是按钮点击。ActionTypes- 用于编码某个动作的映射编解码器注册表。CustomTemplate- 构建一个命令并请求服务器运行它。CustomAll- 从所有输入构建一个自定义服务器点击动作,并请求服务器运行它。ParsedTemplate- 一个编码某些字符串的模板,类似于函数宏的工作方式。StaticAction- 一个在激活时触发ClickEvent的动作。
net.minecraft.server.dialog.bodyDialogBody- 描述标题和动作/输入之间内容的主体元素。DialogBodyTypes- 用于编码某个主体的映射编解码器注册表。ItemBody- 一个带有可选描述的物品。PlainMessage- 一个多行标签。
net.minecraft.server.dialog.inputBooleanInput- 一个带有标签的普通复选框。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.clientCamera现在实现TrackedWaypoint$CameraMinecraft#getWaypointStyles- 返回一个键到路径点样式的管理器。
net.minecraft.client.data.models.WaypointStyleProvider- 一个生成路径点样式的数据提供者。net.minecraft.client.multiplayer.ClientPacketListener#getWaypointManager- 获取用于跟踪路径点的客户端管理器。net.minecraft.client.renderer.GameRenderer现在实现TrackedWaypoint$Projectornet.minecraft.client.resourcesWaypointStyle- 定义用于渲染路径点的样式。WaypointStyleManager- 将某个键映射到路径点样式的管理器。
net.minecraft.client.waypoints.ClientWaypointManager- 用于跟踪路径点的客户端管理器。net.minecraft.commands.arguments.WaypointArgument- 一个静态方法持有者,用于从实体获取某个路径点发射器。net.minecraft.network.protocol.gameClientboundTrackedWaypointPacket- 一个向客户端发送某个路径点操作的数据包。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.entityEntity#getRequiresPrecisePosition、setRequiresPrecisePosition- 处理何时需要更精确的位置进行跟踪。LivingEntity现在实现WaypointTransmitter
net.minecraft.world.waypointsTrackedWaypoint- 一个由某个 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 之前构建。
统一变量重做
统一变量系统已被完全改造,以至于除非您熟悉特定功能,否则它可能看起来完全陌生。简而言之,统一变量现在存储为接口对象、纹素缓冲区或采样器。这些由 GpuBuffer 或 GpuBufferSlice 填充。
统一变量类型
一个统一变量目前表示为两种 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 设置统一变量。唯一的区别是,现在您必须提供一个 GpuBuffer 或 GpuBufferSlice,其中写入了统一数据,而不是提供任意对象。对于纹素缓冲区,这通常是一些所需纹理格式的编码数据(例如网格)。对于接口块,最简单的方法是使用 Std140Builder 用正确的值填充缓冲区。
写入 GpuBuffer 或 GpuBufferSlice 有很多不同的方法,例如使用新创建的 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.buffersBufferType枚举已移除BufferUsage枚举已移除GpuBuffer现在接受两个整数表示大小和用法,不再指定类型type已移除usage现在返回一个 intslice- 返回一个表示某个缓冲区切片的记录。实际缓冲区不以任何方式修改。$ReadView->$MappedView
GpuBufferSlice- 一个记录,通过持有对整个缓冲区的引用、起点的偏移索引和切片的长度来表示某个缓冲区的切片。GpuFence现在是一个接口,其 OpenGL 实现已移至blaze3d.opengl.GlFenceStd140Builder- 一个用于以std140格式布局的接口块的缓冲区插入器。用于着色器中的统一块。Std140SizeCalculator- 一个用于跟踪某个接口块大小的对象。
com.mojang.blaze3d.openglAbstractUniform已移除,被Std140*类取代BufferStorage- 一个根据其类型创建缓冲区的类。其实现定义了其一般用途。DirectStateAccesscreateBuffer- 创建一个缓冲区。bufferData- 初始化缓冲区的数据存储。bufferSubData- 更新缓冲区数据存储的子集。bufferStorage- 创建缓冲区的数据存储。mapBufferRange- 映射缓冲区数据存储的一部分。unmapBuffer- 释放缓冲区的映射并使指向其数据存储的指针无效。
GlBuffer现在接受一个DirectStateAccess、两个整数和一个ByteBuffer,而不是GlDebugLabel及其Buffer*枚举initialized已移除persistentBuffer- 持有对某个缓冲区不可变部分的引用。$ReadView->$GlMappedView
GlCommandEncoderexecuteDrawMultiple现在接受一个字符串集合,定义所需统一变量的列表,以及一个表示绘制调用对象的泛型executeDraw现在接受两个int,要渲染的指定索引范围的实例数和基础顶点
GlConst#toGl用于BufferType和BufferUsage->bufferUsageToGlFlag、bufferUsageToGlEnumGlDebugLabel#pushDebugGroup、popDebugGroup- 用于对类似调用进行分组的分析器命令。GlDeviceUSE_GL_ARB_buffer_storage- 设置GL_ARB_buffer_storage的扩展标志。getBufferStorage- 返回负责创建缓冲区的存储。
GlProgramUniform字段已移除safeGetUniform、setDefaultUniforms已移除bindSampler已移除getSamplerLocations、getSamplers、getUniforms->getUniforms,返回名称到其Uniform对象的映射
GlRenderPassuniforms现在是一个HashMap<String, GpuBufferSlice>dirtSamplers已移除samplers映射现在持有GpuTextureView值pushedDebugGroups- 返回推送到堆栈上的组数。关闭渲染通道时不得有任何调试组打开。isScissorEnabled- 返回是否启用剪裁状态,该状态会裁剪渲染到屏幕的区域。getScissorX、getScissorY、getScissorWidth、getScissorHeight- 返回表示剪裁矩形的值。
GlTexture现在接受一个额外的整数用于用法和深度/层数flushModeChanges现在接受一个表示纹理目标的intaddViews、removeViews- 管理针对某些 mip 级别的纹理视图。
GlTextureView- 针对某些 mip 级别的纹理的视图实现。Uniform现在是一个密封接口,实现为缓冲区对象、纹素缓冲区或采样器
com.mojang.blaze3d.pipelineBlendFunction#PANORAMA已移除CompiledRenderPipeline#containsUniform已移除RenderPipeline$Builder#withUniform现在有一个可以接受TextureFormat的重载$UniformDescription现在接受一个可为 null 的TextureFormat
RenderTargetcolorTextureView、depthTextureView、getColorTextureView、getDepthTextureView- 当前颜色和深度纹理的视图。blitAndBlendToTexture现在接受GpuTextureView而不是GpuTexture
com.mojang.blaze3d.platform.Lightning现在是AutoCloseablesetup*->setupFor,一个接受$Entry的实例方法updateLevel- 更新光照缓冲区,接受是否使用下界漫射光照。
com.mojang.blaze3d.shadersFogShape->net.minecraft.client.renderer.fog.FogData,不是一对一UniformType现在只包含两种类型:UNIFORM_BUFFER或TEXEL_BUFFER,不再接受计数
com.mojang.blaze3d.systemsCommandEncoderclearColorAndDepthTextures现在有一个接受四个int的重载,表示要清除纹理信息的区域writeToBuffer、mapBuffer(GpuBuffer, int, int)现在接受GpuBufferSlice而不是GpuBuffercreateFence- 创建一个新的同步围栏。createRenderPass现在接受一个Supplier<String>,用于确定用作调试组的通道名称,以及GpuTextureView而不是GpuTexturewriteToTexture现在接受一个额外的int,表示要写入的深度或层presentTexture现在接受GpuTextureView而不是GpuTexture
GpuDevicecreateBuffer不再接受BufferUsage,BufferType被int取代getUniformOffsetAlignment- 返回统一缓冲区偏移对齐。createTexture现在接受额外的int用于用法和深度/层数,请参阅GpuTexture常量createTextureView- 为某个 mip 级别范围创建纹理视图。
RenderPassenableScissor已移除bindSampler现在可以接受一个可为 null 的GpuTextureViewsetUniform现在可以接受GpuBuffer或GpuBufferSlice而不是原始输入drawIndexed现在接受以下int:基础顶点、起始索引、元素数和原始计数drawMultipleIndexed现在接受一个字符串集合,定义所需统一变量的列表,以及一个表示绘制调用对象的泛型pushDebugGroup、popDebugGroup- 用于对类似调用进行分组的分析器命令。$UniformUploader#upload现在接受GpuBufferSlice而不是float数组$Draw现在有一个泛型,用于将任何统一变量上传到缓冲区
RenderSystemSCISSOR_STATE->scissorStateForRenderTypeDraws,现在是私有的- 可通过
getScissorStateForRenderTypeDraws访问
- 可通过
enableScissor、disableScissor->enableScissorForRenderTypeDraws、disableScissorForRenderTypeDraws,不是一对一PROJECTION_MATRIX_UBO_SIZE- 返回投影矩阵统一变量的大小setShaderFog、getShaderFog现在处理GpuBufferSlicesetShaderGlintAlpha、getShaderGlintAlpha已移除setShaderLights、getShaderLights现在处理GpuBufferSlicesetShaderColor、getShaderColorsetup*Lighting方法已移除setProjectionMatrix、getProjectionMatrix(现在为getProjectionMatrixBuffer)现在处理GpuBufferSlicesetShaderGameTime、getShaderGameTime->setGlobalSettingsUniform、getGlobalSettingsUniform;不是一对一getDynamicUniforms- 返回要为着色器写入的统一变量列表。bindDefaultUniforms- 绑定要在RenderPass内使用的默认统一变量outputColorTextureOverride、outputDepthTextureOverride现在是GpuTextureViewsetupOverlayColor、setShaderTexture、getShaderTexture现在操作GpuTextureView而不是GpuTexture
com.mojang.blaze3d.texturesGpuTexture现在接受一个表示用法标志和深度/层数的 intusage- 定义纹理如何使用的标志。depthOrLayers、getDepthOrLayers- 定义给定纹理可用的层数或深度。这是作为可用纹理编码的通用计数。目前仅支持立方体贴图(意味着层数必须是 6 的倍数)。
GpuTextureView- 针对某个 mip 级别范围的纹理视图。TextureFormat#RED8I- 处理红色通道的 8 位有符号整数。
com.mojang.blaze3d.vertexByteBufferBuilder现在接受一个 long 作为最大容量exactlySized- 返回一个达到其最大容量的缓冲区。应优先于公共构造函数调用此方法。
DefaultVertexFormat#EMPTY- 一个没有元素的顶点格式。
net.minecraft.client.rendererCachedOrthoProjectionMatrixBuffer- 一个缓存正交投影矩阵的对象,如果屏幕宽度或高度改变,则重新构建。CachedPerspectiveProjectionMatrixBuffer- 一个缓存透视投影矩阵的对象,如果宽度、高度或视野改变,则重新构建。CloudRendererFLAG_INSIDE_FACE、FLAG_USE_TOP_COLOR现在是私有的RADIUS_BLOCKS已移除endFrame- 通过构造围栏结束当前正在渲染的帧。
CubeMap现在是AutoCloseablerender不再接受部分刻的浮点数。
DynamicUniforms- 一个将统一接口块写入缓冲区以供着色器使用的类。DynamicUniformStorage- 一个将统一变量保存在可映射环形缓冲区切片中的类。FogParameters记录已移除,现在存储在一个通用的GpuBufferSlice中FogRenderer现在实现AutoCloseable->.fog.FogRendererendFrame- 通过构造围栏结束当前正在渲染的帧。getBuffer- 获取持有当前雾模式统一变量的缓冲区切片。setupFog不再接受FogMode,不返回任何内容$FogData#mode已移除,被skyEnd、cloudEnd取代$FogMode枚举已被NONE和WORLD取代,不是一对一
GameRenderergetGlobalSettingsUniform- 返回游戏设置的统一变量。getLighting- 获取光照渲染器。setLevel- 设置渲染器正在渲染的当前等级。
GlobalSettingsUniform- 一个用于处理持有当前游戏设置的统一变量的对象。LevelRendererendFrame- 通过构造围栏结束当前正在渲染的帧。renderLevel现在接受一个GpuBufferSlice、雾向量以及当前位置是否有雾,而不是GameRenderer
MappableRingBuffer- 一个包含三个缓冲区的对象,根据需要写入,然后在结束时旋转到下一个要使用的缓冲区。这些使用围栏进行同步。PanoramaRenderer#render现在接受一个布尔值,表示是否改变旋转,而不是两个浮点数。PerspectiveProjectionMatrixBuffer- 一个持有投影矩阵统一变量的对象。PostChainload现在接受CachedOrthoProjectionMatrixBufferaddToFrame不再接受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传入$InputbindTo已移除texture- 根据资源映射为输入构造一个GpuTexture。samplerName- 返回采样器的名称。
SkyRenderer#renderSunMoonAndStars不再接受FogParametersUniformValue- 一个表示存储在接口块内的统一变量的接口。
net.minecraft.client.renderer.chunk.SectionRendererDispatcher$RenderSection#setDynamicTransformIndex、getDynamicTransformIndex- 处理用于查询给定部分的正确动态变换的索引。net.minecraft.client.renderer.fog.environmentAirBasedFogEnvironment- 一个其颜色源自生物群系空气的环境AtmosphericFogEnvironment- 如果没有其他特殊情况匹配,则为默认雾环境。BlindessFogEnvironment- 如果实体有失明效果,则激活的环境。DarknessFogEnvironment- 如果实体有黑暗效果,则激活的环境。DimensionOrBossFogEnvrionment- 根据是否有任何 Boss 或维度特殊效果而激活的环境。FogEnvironment- 一个抽象类,确定雾在给定位置应如何为实体渲染。LavaFogEnvironment- 如果实体在熔岩中,则激活的环境。MobEffectFogEnvironment- 根据实体是否有给定的状态效果而激活的环境。PowderedSnowFogEnvironment- 如果实体在细雪中,则激活的环境。WaterFogEnvironment- 如果实体在水中,则激活的环境。
net.minecraft.client.renderer.textureAbstractTexturesetUseMipmaps- 设置纹理是否应使用 mipmapping。textureView、getTextureView- 表示当前的纹理视图。
CubeMapTexture- 一个兼容立方体贴图的纹理,纹理预期具有后缀_0到_5。ReloadableTexture#doLoad现在是 protected
net.minecraft.world.level.material.FogTypeDIMENSION_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 有五个常见方法:三个添加条目(add、addAll、addOptional),两个添加标签(addTag、addOptionalTag)。可以通过 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.tagsBlockItemTagsProvider- 一个为方块物品生成标签的提供者,使用方块和物品标签等效项作为起点。IntrinsicHolderTagsProvidertag现在返回原始的TagAppender$IntrinsicTagAppender类已移除
ItemTagsProvider类已移除KeyTagProvider- 一个通过其ResourceKey追加元素的提供者。TagsProvidertag已移除$TagAppender->TagAppender,不是一对一
VanillaItemTagsProvider现在实现IntrinsicHolderTagsProviderBlockToItemConverter- 一个将方块添加到物品标签的标签追加器。
通用编码与解码:替换直接 NBT 访问
从更高级别的对象(如实体和方块实体)中获取某些 NBT 数据的直接访问已被完全移除。这意味着,通常,在序列化过程中您不能直接接触 CompoundTag。相反,通过 ValueInput 和 ValueOutput 提供了对 nbt 标签的间接访问。顾名思义,它们分别从数据对象读取值和向数据对象写入值。可用的方法类似于 CompoundTag 上的方法。对于 ValueInput,有通过提供关联键的 get* 方法,以及如果不存在则获取或默认的 get*Or。还有用于处理 Codec 的 read。对于 ValueOutput,有通过提供关联键和值的 put* 方法,以及用于 Codec 的 store。列表变体在输入/输出访问上单独存在。
因此,大多数接受 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 的间接访问,有分别称为 TagValueInput 和 TagValueOutput 的 ValueInput 和 ValueOutput 的实现。
可以使用 createWithContext 或 createWithoutContext 创建 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.ServerPlayerloadAndSpawnParentVehicle现在接受一个ValueInputloadAndSpawnEnderPearls现在接受一个ValueInputloadGameTypes现在接受一个ValueInput
net.minecraft.server.players.PlayerList#load接受一个ProblemReporter,返回一个可选的ValueInputnet.minecraft.util.ProblemReporterDISCARDING- 一个丢弃所有报告的报告器。forChild现在接受一个$PathElementreport现在接受一个$Problem$Collector现在有一个接受根$PathElement的构造函数isEmpty- 返回是否没有报告。forEach- 遍历所有可用问题。getReport现在返回一个普通的StringgetTreeReport- 使用 DFS 获取报告及其所有子级。
$ElementReferencePathElement- 一个引用某个ResourceKey的路径元素。$FieldPathElement- 一个引用某个字符串的路径元素。$IndexedFieldPathElement- 一个在索引处引用某个字符串的路径元素。$IndexedPathElement- 一个引用某个索引的路径元素。$PathElement- 一个定义分组或元素的接口。$Problem- 一个定义元素问题的接口。$RootElementPathElement- 一个引用某个ResourceKey作为根的路径元素。$RootFieldPathElement- 一个引用某个字符串作为根的路径元素。$ScopedCollector- 一个在出现问题时记录警告的收集器。
net.minecraft.worldContainerHelpersaveAllItems现在接受一个ValueOutput而不是CompoundTag,不再接受HolderLookup$Provider,不返回任何内容loadAllItems现在接受一个ValueInput而不是CompoundTag,不再接受HolderLookup$Provider
LockCode#addToTag、fromTag现在接受ValueOutput/ValueInput而不是CompoundTag,不再接受HolderLookup$ProviderRandomziableContainer#tryLoadLootTable、trySaveLootTable现在接受ValueOutput/ValueInput而不是CompoundTagSimpleContainerfromTag->fromItemList,不是一对一createTag->storeAsItemList,不是一对一
net.minecraft.world.entityEntitysaveAsPassenger现在接受一个ValueOutput而不是CompoundTagsave现在接受一个ValueOutput而不是CompoundTagsaveWithoutId现在接受一个ValueOutput而不是CompoundTag,不返回任何内容load现在接受一个ValueInput而不是CompoundTagreadAdditionalSaveData现在接受一个ValueInput而不是CompoundTagaddAdditionalSaveData现在接受一个ValueOutput而不是CompoundTagproblemPath- 返回报告问题的路径元素。
EntityRenferencestore现在接受一个ValueOutput而不是CompoundTagread、readWithOldOwnerConversion现在接受一个ValueInput而不是CompoundTag
EntityUUID_TAG->TAG_UUIDcreate、by现在接受一个ValueInput而不是CompoundTagloadEntityRecursive现在接受一个ValueInput而不是CompoundTagloadEntitiesRecursive现在接受一个ValueInput$ValueInputList而不是 nbt 标签列表loadStaticEntity现在接受一个ValueInput而不是CompoundTag
EntityReference#store- 将引用数据写入ValueOutput。Leashable#readLeashData、writeLeashData现在接受ValueInput/ValueOutput而不是CompoundTagLivingEntity#ATTRIBUTES_FIELD->TAG_ATTRIBUTESNeutralMob#addPersistentAngerSaveData、readPersistentAngerSaveData现在接受ValueOutput/ValueInput而不是CompoundTag
net.minecraft.world.entity.npc.InventoryCarrier#readInventoryFromTag、writeInventoryToTag现在接受ValueInput/ValueOutput而不是CompoundTagnet.minecraft.world.entity.player.Inventorysave现在接受一个ValueOutput$TypedOutputList,不返回任何内容load现在接受一个ValueOutput$TypedInputList
net.minecraft.world.entity.variant.VariantUtilswriteVariant现在接受一个ValueOutput而不是CompoundTagreadVariant现在接受一个ValueInput而不是CompoundTag,不再接受RegistryAccess
net.minecraft.world.entity.vehicle.ContainerEntity#addChestVehicleSaveData、readChestVehicleSaveData现在接受ValueOutput/ValueInput而不是CompoundTag,不再接受HolderLookup$Providernet.minecraft.world.inventory.PlayerEnderChestContainerfromTag->fromSlots,不是一对一createTag->storeAsSlots,不是一对一
net.minecraft.world.itemBlockItem#setBlockEntityData现在接受一个TagValueOutput而不是CompoundTagItemStack#parse、save已移除
net.minecraft.world.levelBaseCommandBlock#save、load现在接受ValueOutput/ValueInput而不是CompoundTag,不再接受HolderLookup$Provider,不返回任何内容BaseSpawner#save、load现在接受ValueOutput/ValueInput而不是CompoundTag,不返回任何内容
net.minecraft.world.level.block.SculkSpreader#save、load现在接受ValueOutput/ValueInput而不是CompoundTagnet.minecraft.world.level.block.entity.BlockEntityload*方法现在接受ValueInput而不是CompoundTag,不再接受HolderLookup$Providersave*方法现在接受ValueOutput而不是CompoundTag,不再接受HolderLookup$ProviderremoveComponentsFromTag现在接受一个ValueOutput而不是CompoundTagparseCustomNameSafe现在接受一个ValueInput和键,而不是标签和HolderLookup$ProviderproblemPath- 返回报告问题的路径元素。
net.minecraft.world.level.block.entity.trialspawner.TrialSpawner#load、store- 处理写入生成器数据。net.minecraft.world.level.chunk.ChunkAccess#problemPath- 返回报告问题的路径元素。net.minecraft.world.level.storagePlayerDataStorage#load现在返回一个ValueInput而不是CompoundTag,接受一个ProblemReporterTagValueInput- 一个复合标签输入。TagValueOutput- 一个复合标签输出。ValueInput- 一个定义如何从某个对象读取数据的接口。ValueInputContextHelper- 一个包含用于读取对象数据的上下文的类。ValueOutput- 一个定义如何向某个对象写入数据的接口。
net.minecraft.world.level.storage.loot.ValidationContextforChild、enterElement现在接受ProblemReporter$PathElement而不是StringreportProblem现在接受ProblemReporter$Problem而不是String$MissingReferenceProblem- 一个引用对象缺失的问题。$ParametersNotProvidedProblem- 一个战利品上下文参数缺失的问题。$RecursiveReferenceProblem- 一个引用对象正在引用自身的问题。$ReferenceNotAllowedProblem- 一个引用对象不允许被引用的问题。
net.minecraft.world.level.storage.loot.entriesAlternativesEntry#UNREACHABLE_PROBLEM- 一个替代条目永远无法执行的问题。CompositeEntryBase#NO_CHILDREN_PROBLEM- 一个组合体没有条目的问题。NestedLootTable#INLINE_LOOT_TABLE_PATH_ELEMENT- 一个表示表是内联的元素。
服务端玩家变更
MinecraftServer 不再在 ServerPlayer 上公开。此外,serverLevel 已被移除,现在用重载的 level 来返回 ServerLevel。
net.minecraft.server.level.ServerPlayerserver字段现在是私有的serverLevel->level,仍然返回ServerLevel
小幅迁移
以下是有用或有趣的增加、变更和移除的列表,它们不值得在入门文档中拥有自己的章节。
拴绳
拴绳系统已更新,最多支持四个拴绳同时拴在一个实体上。此外,物理效果已更新,以更恰当地处理某些可拉伸物体的现实弹性。
net.minecraft.client.renderer.entity.state.EntityRenderStateleashState现在返回一个$LeashState列表$LeashState#slack- 拴绳是否有松弛。
net.minecraft.world.entityEntityshearOffAllLeashConnections- 处理使用剪刀移除拴绳时的情况。dropAllLeashConnections- 处理应从实体移除所有拴绳时的情况。getQuadLeashHolderOffsets- 获取四个拴绳拴在实体上时的偏移量。supportQuadLeashAsHolder- 返回实体是否可以被拴最多四次。notifyLeashHolder、notifyLeasheeRemoved- 处理拴绳在实体上Tick以及被移除时的情况。setLeashOffset已移除getLeashOffset->Leashable#getLeashOffset
LeashableMAXIMUM_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- 通知实体拴绳已附着。elasticRangeLeashBehaviour、legacyElasticRangeLeashBehaviour->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.multiplayerClientPacketListenergetCommands现在返回一个ClientSuggestionProvider泛型sendUnattendedCommand现在接受一个Screen而不是boolean
ClientSuggestionListener现在实现PermissionSource,接受一个布尔值表示是否允许受限命令allowRestrictedCommands- 返回是否建议受限命令。
net.minecraft.commandsCommands#hasPermission- 返回给定级别的权限检查。CommandSourceStack现在实现PermissionSourceExecutionCommandSource现在实现PermissionSourcePermissionSource- 返回运行命令的权限源。SharedSuggestionProvidersuggestResgitryElements现在接受HolderLookup而不是RegistrylistSuggestions- 列出某些注册表元素的建议。hasPermission已移除
net.minecraft.commands.synchronization.SuggestionProvidersAVAILABLE_SOUNDS、SUMMONABLE_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.animationAnimationDefinition#bake- 烘焙一个已定义的动画,以便在Model上使用。KeyframeAnimation- 一个用于在给定Model上移动ModelPart的烘焙动画。KeyframeAnimations#animate->KeyframeAnimation$Entry#apply
net.minecraft.client.model.ModelgetAnyDescendantWithName已移除animate->KeyframeAnimation#applyanimateWalk-KeyframeAnimation#applyWalkapplyStatic->KeyframeAnimation#applyStatic
net.minecraft.client.model.geom.ModelPartgetAllParts现在返回一个ListcreatePartLookup- 创建一个部件名称到其ModelPart的查找表,任何重复的名称将被忽略。
ChunkSectionLayers
用于定义方块或流体应如何渲染的 RenderType 现在已被 ChunkSectionLayer 取代。它们在功能上与 RenderType 相同;然而,它们只指定要使用的 RenderPipeline 以及缓冲区信息。这也意味着某些 RenderType 被移除,例如 TRANSLUCENT,因为它们仅用于区块渲染。
这也意味着添加到 ItemBlockRenderTypes#TYPE_BY_BLOCK 必须指定 ChunkSectionLayer 而不是关联的 RenderType。
net.minecraft.client.rendererItemBlockRenderTypesgetChunkRenderType现在返回一个ChunkSectionLayergetRenderLayer(FluidState)现在返回一个ChunkSectionLayer
RenderTypetranslucent已移除getRenderTarget、getRenderPipeline已移除chunkBufferLayers已移除
net.minecraft.client.renderer.chunkChunkSectionLayer- 一个枚举,定义如何渲染单个区块层(例如,实心方块、半透明方块)。ChunkSectionLayerGroup- 一个枚举,将层分组以进行渲染。ChunkSectionsToRender- 一个记录,包含给定区块的绘制,允许按层组渲染它们。RenderChunk->SectionCopyRenderChunkRegion->RenderSectionRegionRenderRegionCache#createRegion现在接受一个long而不是SectionPosSectionCompiler$ResultsglobalBlockEntities-> -net.minecraft.client.multiplayer.ClientLevel#getGloballyRenderedBlockEntitiesrenderedLayers现在接受ChunkSectionLayer作为键
SectionMesh- 一个定义区块内给定部分的网格的接口SectionRenderDispatchergetBatchToCount->getCompileQueueSizesetCamera、getCameraPosition已移除blockUntilClear已移除clearBatchQueue->clearCompileQueue,现在是公开的$CompiledSection->CompiledSectionMesh$RenderSectiongetBuffers已移除uploadSectionLayer(RenderType, MeshData)->upload(Map, CompiledSectionMesh),不是一对一uploadSectionIndexBuffer现在接受一个CompiledSectionMesh和一个ChunkSectionLayer而不是RenderTypegetDistToPlayerSqr已移除getCompiled->getSectionMesh,不是一对一rebuildSectionAsync不再接受SectionRenderDispatchersetDynamicTransformIndex、getDynamicTransformIndex已移除
$SectionBuffers->SectionBuffers$TranslucencyPointOfView->TranslucencyPointOfView
net.minecraft.server.level.ChunkMap#getUpdatingChunkIfPresent现在是公开的net.minecraft.world.level.TicketStoragepurgeStaleTickets现在接受ChunkMapremoveTicketIf现在接受一个BiPredicate而不是Predicate,接受区块位置和加载票
net.minecraft.world.level.chunk.ChunkAccess#isSectionEmpty已移除
标签变更
minecraft:blockplays_ambient_desert_block_sounds拆分为triggers_ambient_desert_sand_block_sounds、triggers_ambient_desert_dry_vegetation_block_soundshappy_ghast_avoidstriggers_ambient_dried_ghast_block_sounds
minecraft:dialogpause_screen_additionsquick_actions
minecraft:entity_typecan_equip_harnessfollowable_friendly_mobs
minecraft:itemharnesseshappy_ghast_foodhappy_ghast_tempt_items
新增列表
com.mojang.blaze3d.pipelineBlendFunction#TRANSLUCENT_PREMULTIPLIED_ALPHA- 一个假设目标具有来自合成步骤的预乘 alpha 的混合函数。RenderPipelinegetSortKey- 返回一个表示元素应如何排序以进行渲染的值。用于层排序。updateSortKeySeed- 更新排序键的种子,当前未使用。
com.mojang.blaze3d.systems.RenderSystemoutputColorTextureOverride- 持有一个包含覆盖颜色的纹理,该覆盖颜色将代替RenderType目标中指定的任何内容使用。outputDepthTextureOverride- 持有一个包含覆盖深度的纹理,该覆盖深度将代替RenderType目标中指定的任何内容使用。
com.mojang.blaze3d.textures.GpuTexture#setUseMipmaps- 设置纹理在不同距离是否应使用 mipmap。net.minecraftFileUtil#isPathPartPortable- 返回提供的字符串是否与任何 Windows 保留文件名不匹配。WorldVersion$Simple- 当前世界版本的简单实现。
net.minecraft.advancements.critereonItemUsedOnLocationTrigger$TriggerInstance#placedBlockWithProperties- 创建一个触发器,其中放置了一个具有指定属性的方块。PlayerInteractTrigger$TriggerInstance#equipmentSheared- 创建一个条件触发器,作用于玩家从某个实体上取下物品。
net.minecraft.clientGameNarrator#saySystemChatQueued- 如果启用了系统或聊天消息旁白,则旁白一个组件。Minecraft#disconnectWithSavingScreen- 断开当前客户端实例并显示“保存等级”屏幕。OptionskeyQuickActions- 用于显示快速操作对话框的按键映射。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.modelModelTemplates#DRIED_GHAST- 一个使用minecraft:block/dried_ghast父级的模板。TextureMapping#driedGhast- 为干燥恶魂模型创建默认纹理映射。TextureSlot#TENTACLES- 提供一个纹理键tentacles。
net.minecraft.client.modelGhastModel#animateTentacles- 动画恶魂的触手。HappyGhastHarnessModel- 一个代表恶魂挽具的模型。HappyGhastModel- 一个代表“驯服”恶魂的模型。QuadrupedModel#createBodyMesh现在接受两个布尔值,分别用于处理左后腿和右后腿纹理是否镜像。
net.minecraft.client.multiplayer.ClientLevelDEFAULT_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.soundsMusicManagergetCurrentMusicTranslationKey- 返回当前正在播放的音乐的翻译键。setMinutesBetweenSongs- 设置背景曲目之间的频率。showNowPlayingToastIfNeeded- 如果需要,显示正在播放吐司。$MusicFrequency- 正在播放的背景曲目的频率。
SoundEngine$PlayResult- 尝试播放的声音的起始状态。
net.minecraft.commands.argumentsHexColorArgument- 一个接受十六进制颜色的整数参数。ResourceOrIdArgumentcreateGrammar- 创建用于解析参数的语法。$InlineResult- 一个返回直接持有者的结果。$ReferenceResult- 一个返回引用持有者的结果。$Result- 一个表示某个参数解析结果的接口。
net.minecraft.data.loot.LootTableProvider$MissingTableProblem- 一个记录,保存某个缺失的内置表生成器的键。net.minecraft.data.recipes.RecipeProviderdryGhast- 干燥恶魂的配方。harness- 染色挽具的配方。
net.minecraft.gametest.framework.GameTestTicker#startTicking- 开始为游戏测试Tick运行器。net.minecraft.nbt.NbtUtilsaddCurrentDataVersion、addDataVersion,将数据版本添加到某个 nbt 标签。
net.minecraft.network.FriendlyByteBuf#writeEither、readEither- 使用给定的流编码器/解码器处理Either。net.minecraft.network.codec.ByteBufCodecsRGB_COLOR- 一个使用三个字节写入 RGB 的流编解码器。lenientJson- 创建一个以宽松模式解析 json 的流编解码器。optionalTagCodec- 创建一个使用提供的NbtAccounter解析Optional包装的Tag的流编解码器。
net.minecraft.network.protocol.gameServerboundChangeGameModePacket- 更改当前游戏模式。ServerboundCustomClickActionPacket- 在服务器上执行自定义操作,目前什么都不做。
net.minecraft.server.MinecraftServer#handleCustomClickAction- 处理从点击事件发送的自定义操作。net.minecraft.server.level.ServerLevelupdateNeighboursOnBlockSet- 更新当前位置的邻居。如果方块不相同(不包括其属性),则调用BlockState#affectNeighborsAfterRemoval。waitForChunkAndEntities- 添加一个任务,使服务器等待,直到实体在提供的区块范围内加载。
net.minecraft.sources.SoundSource#UI- 来自某些用户界面的声音。net.minecraft.statsRecipeBookSettings#MAP_CODECServerRecipeBook#pack、loadUntrusted、$Packed- 处理编码和解码配方书的数据。
net.minecraft.utilARGBsetBrightness- 使用 0 到 1 之间的浮点数返回某个颜色的亮度。color- 从浮点红色和整数 alpha 返回一个 ARGB 颜色。
ExtraCodecsVECTOR2FVECTOR3INBT
LenientJsonParser- 一个使用宽松规则的 json 解析器。Mth#smallestSquareSide- 取一个数的平方根的上取整。StrictJsonParser- 一个使用严格规则的 json 解析器。
net.minecraft.worldDifficulty#STREAM_CODECItemStackWithSlot- 一个记录,包含一个堆栈及其槽位索引。
net.minecraft.world.entityEntityMAX_MOVEMENTS_HANDELED_PER_TICK- 在给定Tick中可以应用于实体的最大移动数。isInClouds- 返回实体的 Y 位置是否在云高度和其上方四个单位之间。teleportSpectators- 传送当前从玩家视角观看的旁观者。isFlyingVehicle- 返回载具是否可以飞行。clearMovementThisTick- 清除实体在本Tick中将进行的所有移动。
EntityAttachments#getAverage- 返回所有附着点的平均位置。ExperienceOrbawardWithDirection- 添加一个通过指定向量移动的经验球。unstuckIfPossible- 尝试查找并将球移动到空闲位置。
MobisWithinHome- 返回该位置是否在实体的限制半径内。canShearEquipment- 返回当前玩家是否可以从该生物上剪下装备。
net.minecraft.world.entity.ai.control.MoveControl#setWait- 将操作设置为WAIT。net.minecraft.world.entity.ai.goal.TemptGoalstopNavigation、navigateTowards- 处理向玩家的导航。$ForNonPathfinders- 一个引诱目标,它导航到想要的位置,而不是立即寻路。
net.minecraft.world.entity.ai.navigation.PathNavigation#canNavigateGround- 返回实体是否可以在陆地上寻路。net.minecraft.world.entity.ai.sensing.AdultSensorAnyType- 一个忽略实体是否与幼崽相同类型的成年传感器。net.minecraft.world.entity.animalHappyGhast- 一个代表快乐恶魂的实体。HappyGhastAi- 快乐恶魂的大脑。
net.minecraft.world.entity.decoration.ArmorStandsetArmorStandPose、getArmorStandPose、$ArmorStandPose- 处理盔甲架的姿势。
net.minecraft.world.entity.monster.GhastfaceMovementDirection- 旋转实体以面对其当前移动方向。$RandomFloatAroundGoal#getSuitableFlyToPosition- 获取恶魂应飞向的位置。
net.minecraft.world.entity.player.Inventory#SLOT_BODY_ARMOR、SLOT_SADDLE- 相应槽位的索引。net.minecraft.world.entity.projectile.ProjectileUtil#computeMargin- 根据其Tick计数计算要检查的给定实体的边界框边距。net.minecraft.world.item.componentItemAttributeModifiersforEach- 将消费者应用于槽位组内的所有属性。$Builder#add- 添加一个要应用于给定槽位组的属性,并带有显示。$Display- 定义属性修改器应如何在其工具提示中显示。$Default- 显示默认属性显示。$Hidden- 不显示任何属性信息。$OverrideText- 用提供的组件覆盖属性文本。
Equippable$BuildersetCanBeSheared- 设置装备是否可以从实体上剪下。setShearingSound- 设置从实体上剪下一件装备时要播放的声音。
ResolvableProfile#pollResolve- 返回存储的 id 或名称的配置文件。
net.minecraft.world.item.equipment.Equippable#harness- 表示要装备的挽具。net.minecraft.world.levelCollisionGettergetPreMoveCollisions- 返回一个包含给定边界框和未来移动方向上的实体和方块碰撞的形状的可迭代对象。getBlockCollisionsFromContext- 从给定的碰撞上下文中获取方块形状。
GameType#STREAM_CODECLevelprecipitationAt- 返回给定位置的降水。onBlockEntityAdded- 当方块实体被添加到等级时要运行的逻辑。
net.minecraft.world.level.blockBaseRailBlock#rotate- 在关联方向上旋转当前的铁轨形状。DriedGhastBlock- 一个代表干燥恶魂的方块。
net.minecraft.world.level.block.entity.trialspawner.TrialSpawner$FullConfig- 代表试炼的整个配置。net.minecraft.world.level.dimension.DimensionDefaultsCLOUD_THICKNESS- 云的方块厚度。OVERWORLD_CLOUD_HEIGHT- 主世界的云高度等级。
net.minecraft.world.level.levelgen.flat.FlatLayerInfo#heightLimited- 返回一个新的层信息,当前高度是否限制为指定值,只要该值不在最大范围内。net.minecraft.world.physAABBintersects- 返回BlockPos是否与此框相交。distanceToSqr- 返回边界框从其最远点的平方距离。
Vec3#rotateClockwise90- 将向量顺时针旋转 90 度(翻转 x 和 z 并反转新的 x 值)。
net.minecraft.world.phys.shapes.CollisionContextwithPosition- 返回实体的碰撞上下文及其底部 y 位置。
变更列表
com.mojang.blaze3d.platform.Window#setGuiScale、getGuiScale现在处理int而不是doublenet.mineraftDetectedVersion不再实现WorldVersionWorldVersion方法由于使用WorldVersion$Simple而使用记录命名模式getDataVersion->dataVersiongetId->idgetName->namegetProtocolVersion->protocolVersiongetPackVersion->packVersiongetBuildTime->buildTimeisStable->stable
net.minecraft.clientGameNarratorsayChat->sayChatQueuedsay->saySystemQueuedsayNow->saySystemNow
MinecraftgrabPanoramixScreenshot不再接受要设置的窗口宽度和高度disconnect()->disconnectWithProgressScreen
Screenshot#grab、takeScreenshot现在接受一个表示缩小因子的int
net.minecraft.client.main.GameConfig$QuickPlayData现在接受一个$QuickPlayVariantpath->logPathsingleplayer->variant带有$QuickPlaySinglePlayerDatamultiplayer->variant带有$QuickPlayMultiplayerDatarealms->variant带有$QuickPlayRealmsData- 对于
singleplayer、multiplayer、realms的 null 由带有$QuickPlayDisabled的variant表示
net.minecraft.client.data.models.ItemModelGenerators#generateWolfArmor->generateTwoLayerDyedItemnet.minecraft.client.gui.components.DebugScreenOverlay#render3dCrosshair现在接受当前的Cameranet.minecraft.client.gui.components.debugchart.ProfilerPieChartRADIUS现在是公开的CHART_Z_OFFSET->PIE_CHART_THICKNESS,现在是公开的
net.minecraft.client.multiplayerClientLevel$ClientLevelData#getClearColorScale->voidDarknessOnsetRange,不是一对一MultiPlayerGameMode#createPlayer现在接受一个Input而不是boolean
net.minecraft.client.player.LocalPlayer现在接受最后发送的Input而不是 shift 键的booleangetLastSentInput- 获取从服务器最后发送的输入。
net.minecraft.client.quickplay.QuickPlay#connect现在接受GameConfig$QuickPlayVariant而不是GameConfig$QuickPlayDatanet.minecraft.client.rendererDimensionSpecialEffects不再接受当前云级别以及是否有地面LightTexture#getTarget->getTexture
net.minecraft.client.renderer.blockentity.BlockEntityRenderer#shouldRenderOffscreen不再接受BlockEntitynet.minecraft.client.resourcesAbstractSoundInstance#sound现在是NullableSoundInstance#getSound现在是Nullable
net.minecraft.client.soundsSimpleSoundInstance#forMusic现在也接受float音量SoundEngine现在接受MusicManagerpause->pauseAllExcept,不是一对一play现在返回一个$PlayResult
SoundManager现在接受MusicManagerpause->pauseAllExcept,不是一对一play现在返回一个SoundEngine$PlayResult
net.minecraft.commands.argumentsResourceOrIdArgument现在接受一个任意编解码器,而不是Holder包装的值ERROR_INVALID->ERROR_NO_SUCH_ELEMENT,现在是公开的,不是一对一VALUE_PARSER->OPS,现在是公开的,不是一对一
ResourceSelectorArgument#getSelectedResources不再接受ResourceKey
net.minecraft.commands.functions.StringTemplatefromString不再接受行号isValidVariableName现在是公开的
net.minecraft.data.recipes.RecipeProvider#colorBlockWithDye->colorItemWithDye,现在接受RecipeCategorynet.minecraft.gametest.framework.GameTestInfo#prepareTestStructure现在可为 nullnet.minecraft.networkConnection#send现在接受一个ChannelFutureListener而不是PacketSendListenerFriendlyByteBuf#readJsonWithCodec->readLenientJsonWithCodecPacketSendListener现在是一个类,其方法返回ChannelFutureListener而不是PacketSendListeneronSuccess、onFailure已移除
net.minecraft.network.codecByteBufCodecs#fromCodec现在有一个接受某些 ops 和一个编解码器的重载StreamCodec#composite现在有一个接受十个参数的重载
net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket现在是一个记录net.minecraft.network.protocol.gameClientboundChangeDifficultyPacket现在是一个记录ClientboundCommandsPacket现在接受一个$NodeInspectorgetRoot现在是泛型的,接受一个$NodeBuilder$NodeBuilder- 一个给定命令的构建器。$NodeInspector- 一个检查给定命令节点信息的代理。
ServerboundChangeDifficultyPacket现在是一个记录
net.minecraft.server.ReloadableServerRegistries$Holder#lookup返回一个HolderLookup$Providernet.minecraft.server.network.ServerCommonPacketListenerImpl#send现在接受一个ChannelFutureListener而不是PacketSendListenernet.minecraft.sounds.Music现在是一个记录net.minecraft.stats.RecipeBookSettingsgetSettings现在是公开的$TypeSettings现在是公开的
net.minecraft.world.entityAreaEffectCloud#setParticle->setCustomParticleEntitycheckSlowFallDistance->checkFallDistanceAccumulationcollidedWithFluid、collidedWithShapeMovingFrom现在是公开的canBeCollidedWith现在接受与其碰撞的实体spawnAtLocation现在有一个接受Vec3作为偏移位置的重载removeLatestMovementRecordingBatch->removeLatestMovementRecording
EntityReference现在是 finalExperienceOrb现在有一个接受两个向量作为位置和移动的重载FlyingMob被调用LivingEntity#travelFlying取代LivingEntity#canBreatheUnderwater不再是finalMobrestrictTo->setHomeTogetRestrictCenter->getHomePositiongetRestrictRadius->getHomeRadiusclearRestriction->clearHomehasRestriction->hasHome
net.minecraft.world.entity.ai.attributesAttributeInstancesave->pack、$Packed;不是一对一load->apply,不是一对一
AttributeMapsave->pack;不是一对一load->apply,不是一对一
net.minecraft.world.entity.ai.behaviorAnimalPanic现在有接受半径或位置获取器的重载BabyFollowAdult#create现在返回一个OneShot<LivingEntity>,并且可以接受一个boolean表示是否瞄准眼睛位置EntityTracker现在可以接受一个boolean表示是否瞄准眼睛位置FollowTemptation现在有一个重载,检查实体是否需要跟踪实体的眼睛高度。
net.minecraft.world.entity.ai.goal.TemptGoal现在有一个接受停止距离的重载mob现在是一个MobspeedModifier现在是protected
net.minecraft.world.entity.ai.memory.MemoryModuleType#NEAREST_VISIBLE_ADULT现在持有LivingEntitynet.minecraft.world.entity.ai.navigationFlyingPathNavigation、GroundPathNavigation#setCanOpenDoors->PathNavigation#setCanOpenDoors
net.minecraft.world.entity.ai.sensing.AdultSensor现在查找LivingEntitysetNearestVisibleAdult现在是protected
net.minecraft.world.entity.animal.*Variants#selectVariantToSpawn->entity.variant.VariantUtils#selectVariantToSpawn,不是一对一net.minecraft.world.entity.animal.Fox#isJumping->LivingEntity#isJumpingnet.minecraft.world.entity.animal.horse.AbstractHorseisJumping->LivingEntity#isJumpingsetStanding现在接受一个int而不是boolean作为站立计数器false逻辑已移至clearStanding
net.minecraft.world.entity.monsterGhast现在实现Mob$GhastLookGoal现在是公开的,接受一个Mob$GhastMoveControl现在是公开的,接受一个布尔值表示移动时是否应小心,以及一个提供的布尔值表示恶魂是否应停止移动$RandomFloatAroundGoal现在是public,接受一个Mob和一个方块距离
Phantom现在实现Mob
net.minecraft.world.entity.playerAbilitiesaddSaveData->pack、$Packed;不是一对一loadSaveData->apply,不是一对一
Player不再接受BlockPos和 y 旋转
net.minecraft.world.entity.projectileAbstractThrownPotion#onHitAsPostion现在接受一个HitResult而不是可为 null 的EntityEyeOfEnder#signalTo现在接受一个Vec3而不是BlockPosProjectileownerUUID、cachedOwner->owner,现在是 protected;不是一对一setOwner现在有一个接受EntityReference的重载
ProjectileUtilDEFAULT_ENTITY_HIT_RESULT_MARGIN现在是公开的getEntityHitResult现在接受一个Projectile而不是Entity
net.minecraft.world.item.ItemStackforEachModifier现在接受一个提供修改器显示的TriConsumerhurtAndBreak现在有一个重载,从InteractionHand获取EquipmentSlot
net.minecraft.world.item.equipment.Equippable现在接受装备是否可以从实体上剪下以及剪下时要播放的声音net.minecraft.world.level.BlockGetterforEachBlockIntersectedBetween现在返回一个布尔值,表示在相交区域中访问的每个方块是否可以成功访问$BlockStepVisitor#visit现在返回是否可以成功移动到该位置
net.minecraft.world.level.block.AbstractCauldronBlock#SHAPE现在是 protectednet.minecraft.world.level.block.entityBlockEntity#getNameForReporting现在是公开的SignBlockEntity#executeClickCommandsIfPresent现在接受一个ServerLevel而不是Level,参数重新排序StructureBlockEntity#saveStructure现在接受一个要忽略的方块列表
net.minecraft.world.level.block.entity.trialspawnerTrialSpawner现在接受一个$FullConfiggetConfig->activeConfigget*Config->*configgetData->getStateData
TrialSpawnerData->TrialSpawnerStateData,序列化形式为TrialSpawnerStateData$Packed,不是一对一
net.minecraft.world.level.block.sounds.AmbientDesertBlockSoundsPlayer#playAmbientBlockSounds已拆分为playAmbientSandSounds、playAmbientDryGrassSounds、playAmbientDeadBushSounds、shouldPlayDesertDryVegetationBlockSounds;不是一对一net.minecraft.world.level.dimension.DimensionType现在接受一个可选的整数表示云高度等级net.minecraft.world.level.entityPersistentEntitySectionManager#processPendingLoads现在是公开的UUIDLookup#getEntity现在可以返回 null
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate#fillFromWorld现在接受一个要忽略的方块列表,而不是单个Blocknet.minecraft.world.level.storage.DataVersion现在是一个记录net.minecraft.world.phys.shapes.CollisionContext#placementContext现在接受一个Player而不是Entity
移除列表
net.minecraft.client.Minecraft#disconnect(Screen)net.minecraft.client.rendererDimensionSpecialEffects#getCloudHeight、hasGroundLevelRenderer#updateGlobalBlockEntities
net.minecraft.client.renderer.texture.AbstractTexturedefaultBlursetFilter
net.minecraft.network.chat.Component$Serializer、$SerializerAdapternet.minecraft.network.protocol.game.ServerboundPlayerCommandPacket$Action#*_SHIFT_KEYnet.minecraft.server.ReloadableServerRegistries$Holder#getKeysnet.minecraft.server.players.PlayerList#getPlayerForLoginnet.minecraft.statsRecipeBookSettings#read、writeServerRecipeBook#toNbt、fromNbt
net.minecraft.utilGsonHelper#fromNullableJson(..., boolean)、fromJson(..., boolean)LowerCaseEnumTypeAdapterFactory
net.minecraft.world.entity.ai.attributes.AttributeInstance#ID_FIELD、TYPE_CODECnet.minecraft.world.entity.animal.horse.AbstractHorse#setIsJumpingnet.minecraft.world.entity.animal.sheep.Sheep#getColornet.minecraft.world.entity.monster.Drowned#waterNavigation、groundNavigationnet.minecraft.world.entity.projectile.Projectile#findOwner、setOwnerThroughUUIDnet.minecraft.world.level.Level#disconnect()net.minecraft.world.level.blockAbstractCauldronBlock#isEntityInsideContentTerracottaBlock
net.minecraft.world.level.block.entity.trialspawner.TrialSpawner*_CONFIG_TAG_NAMEcodec
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而不是ItemStackRenderStateitemStackRenderState现在返回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
)
);
为了能够正确检查更新,所使用的对象必须正确实现 hashCode 和 equals,而不是依赖对象标识。
调试源
那么,我们如何告诉同步器跟踪和更新我们的 DebugSubscription?您可以扩展 TrackingDebugSynchronizer 或其子类,并通过修补 LevelDebugSynchronizers 或创建自己的类来实现跟踪和同步逻辑。但是,如果您要跟踪的数据直接附加到 LevelChunk、Entity 或 BlockEntity,并且可以从其关联的服务器对象更新,则可以使用 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.SharedConstantsDEBUG_SHUFFLE_MODELS- 一个可能打乱模型加载顺序的标志。DEBUG_FLAG_PREFIX- 放在每个调试标志前面的前缀。USE_DEBUG_FEATURES->DEBUG_ENABLEDDEBUG_RENDER已移除DEBUG_WORLDGENATTEMPT已移除debugGenerateStripedTerrainWithoutNoise已移除DEBUG_RESOURCE_GENERATION_OVERRIDE已移除DEBUG_POI- 启用 POI 调试渲染器。DEBUG_PANORAMA_SCREENSHOT- 启用时,允许用户拍摄全景截图。DEBUG_CHASE_COMMAND- 启用时,添加 chase 命令。FAKE_MS_LATENCY->DEBUG_FAKE_LATENCY_MSFAKE_MS_JITTER->DEBUG_FAKE_JITTER_MSDEBUG_VERBOSE_COMMAND_ERRORS- 启用时,通过聊天框输出详细错误。DEBUG_DEV_COMMANDS- 启用时,添加用于调试游戏的命令。
net.minecraft.client.MinecraftdebugEntries- 返回一个调试功能列表以及应在屏幕上显示的内容。fpsString、sectionPath、sectionVisibility已移除debugRenderer->LevelRenderer#debugRenderer
net.minecraft.client.gui.GuirenderDebugOverlay现在是公开的shouldRenderDebugCrosshair已移除
net.minecraft.client.gui.components.DebugScreenOverlaydrawGameInformation、drawSystemInformation已移除getGameInformation、getSystemInformation已移除toggleOverlay已移除
net.minecraft.client.gui.components.debugDebugEntryBiome- 一个显示相机实体所在生物群系的调试条目。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.LevelRenderergetSectionStatistics现在可为 nullgetEntityStatistics现在可为 nullgameTestBlockHighlightRenderer- 游戏测试中方块高亮的渲染器。
net.minecraft.client.renderer.debug.DebugRendererswitchRenderChunkborder->DebugScreenEntries#CHUNK_BORDERS,不是一对一toggleRenderOctree->DebugScreenEntries#CHUNK_SECTION_OCTREE,不是一对一
net.minecraft.client.multiplayerDebugSampleSubscriber->ClientDebugSubscriber,不是一对一ClientPacketListener#createDebugValueAccess- 创建用于获取当前调试值的访问器。
net.minecraft.client.renderer.debugBeeDebugRenderer#addOrUpdateHiveInfo、addOrUpdateBeeInfo、removeBeeInfo已移除BrainDebugRendereraddPoi、removePoi、$PoiInfo已移除setFreeTicketCount已移除addOrUpdateBrainDump、removeBrainDump已移除
BreezeDebugRenderer现在实现DebugRenderer$SimpleDebugRendererrender现在接受一个DebugValueAccessclear、add已移除
DebugRenderer不再接受Minecraft实例- 所有字段渲染器已从公共访问中移除,而是存储在某个
*Renderers列表中 worldGenAttemptRenderer已移除renderTextOverBlock- 在提供的方块位置上方渲染给定的流。renderTextOverMob- 在提供的实体上方渲染给定的字符串。refreshRendererList- 使用启用的调试渲染器填充渲染器列表。render、renderAfterTranslucents已合并到render中,其中boolean决定是渲染半透明还是不透明的渲染器$SimpleDebugRendererrender现在接受一个DebugValueAccess和Frustumclear已移除
- 所有字段渲染器已从公共访问中移除,而是存储在某个
EntityBlockIntersectionDebugRenderer- 一个用于显示实体相交的方块的调试渲染器。GameEventListenerRenderer不再接受Minecraft实例trackGameEvent、trackListener已移除
GameTestDebugRenderer->GameTestBlockHighlightRenderer,不是一对一addMarker->highlightPos,不是一对一
GoalSelectorDebugRenderer#addGoalSelector、removeGoalSelector已移除NeighborsUpdateRenderer不再接受Minecraft实例addUpdate已移除
OctreeDebugRenderer现在实现DebugRenderer$SimpleDebugRendererPathfindingRenderer#addPath已移除PoiDebugRenderer- 一个用于显示兴趣点的调试渲染器。RaidDebugRenderer#setRaidCenters已移除RedstoneWireOrientationsRenderer不再接受Minecraft实例addWireOrientation已移除
StructureRenderer不再接受Minecraft实例addBoundingBox已移除
VillagerSectionsDebugRenderer#setVillageSection、setNotVillageSection已移除WorldGenAttemptRenderer类已移除
net.minecraft.core.registries.BuiltInRegistries、Registries#DEBUG_SUBSCRIPTION- 调试处理程序订阅的注册表。net.minecraft.gametest.frameworkGameTestAssertPosException#getMessageToShowAtBlock现在返回一个ComponentGameTestRunner#clearMarkers已移除
net.minecraft.network.protocol.common.custom- 所有类已移至
net.minecraft.util.debug - 它们不再是有效负载,而是仅包含对象信息和关联流编解码器的记录
- 如果有效负载类有一个关联的内部对象类,则该类被移动,有效负载类被移除
- 否则,有效负载类被添加,没有
*Payload后缀,大多数情况下带有*Info后缀
- 所有类已移至
net.minecraft.network.protocol.gameClientboundDebugBlockValuePacket- 发送到客户端的数据包,关于方块位置上的调试值更改。ClientboundDebugChunkValuePacket- 发送到客户端的数据包,关于区块位置上的调试值更改。ClientboundDebugEntityValuePacket- 发送到客户端的数据包,关于实体上的调试值更改。ClientboundDebugEventPacket- 发送到客户端的数据包,关于触发的调试事件。ClientboundGameTestHighlightPosPacket- 发送到客户端的数据包,关于要高亮的游戏测试位置。ClientGamePacketListenerhandleDebugChunkValue- 处理调试区块位置数据包。handleDebugBlockValue- 处理调试方块位置数据包。handleDebugEntityValue- 处理调试实体数据包。handleDebugEvent- 处理触发的调试事件。handleGameTestHighlightPos- 处理提供的高亮位置。
DebugPackets类已移除ServerboundDebugSampleSubscriptionPacket->ServerboundDebugSubscriptionRequestPacket,不是一对一ServerGamePacketListener#handleDebugSampleSubscription->handleDebugSubscriptionRequest,不是一对一
net.minecraft.server.MinecraftServersubscribeToDebugSample已移除debugSubscribers- 返回已跟踪订阅到已启用它的玩家列表的映射。
net.minecraft.server.levelChunkMapisChunkTracked现在是公开的getChunks已移除
ServerLevel#debugSynchronizers- 返回等级的调试器处理程序和同步器。ServerPlayerrequestDebugSubscriptions- 设置玩家正在监听的调试器。debugSubscriptions- 返回玩家正在监听的调试器。
net.minecraft.util.debugDebugSubscription- 一个可以监听或订阅的跟踪数据点。DebugSubscriptions- 原版调试订阅。DebugValueAccess- 访问调试订阅跟踪的值,在客户端上用于调试渲染器。DebugValueSource- 定义一个提供要跟踪的调试值的源对象,例如一个实体。LevelDebugSynchronizers- 处理将订阅数据通过网络发送到跟踪客户端。ServerDebugSubscribers- 处理订阅了当前启用订阅的玩家的全局状态。TrackingDebugSynchronizer- 处理订阅了某个订阅的玩家列表。
net.minecraft.util.debugchartDebugSampleSubscriptionTracker类已移除RemoteDebugSampleType现在接受一个DebugSubscriptionsubscription- 返回样本类型报告的订阅。
RemoteSampleLogger现在接受ServerDebugSubscribers而不是DebugSampleSubscriptionTracker
net.minecraft.world.entityEntity现在实现DebugValueSourceMob#sendDebugPackets已移除
net.minecraft.world.entity.ai.village.poiPoiManager#getFreeTickets->getDebugPoiInfo,不是一对一PoiSection#getDebugPoiInfo- 返回给定位置的调试 POI 信息。
net.minecraft.world.level.block.entityBlockEntity现在实现DebugValueSourceTestInstanceBlockEntity#markError、clearErrorMarkers、getErrorMarkers、$ErrorMarker- 处理测试实例设置的错误标记。
net.minecraft.world.level.chunk.LevelChunk现在实现DebugValueSourcenet.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 方法现在接受实体的渲染状态、PoseStack、SubmitNodeCollector 和 CameraRenderState。提交任何元素时,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,它将之前的 SingleQuadParticle 和 TextureSheetParticle 合并为一个。SingleQuadParticle 现在接受一个初始的 TextureAtlasSprite 来设置第一个纹理,然后可以通过覆盖 Particle#tick 并调用 SingleQuadParticle#setSpriteFromAge 来更新 SpriteSet,或者直接使用 setSprite 来更新。色调也可以在Tick中使用 setColor 和 setAlpha 修改。有些也在 SingleQuadParticle#extract 中直接设置,但使用哪个取决于您是否需要覆盖整个Tick。
要确定用于渲染四边形的 RenderType,必须将 SingleQuadParticle#getLayer 设置为所需的 $Layer。$Layer 基本上是一个记录,定义四边形是否可以具有半透明、它从哪个纹理图集拉取以及要使用的渲染管线。原版提供了类似于旧 Particle#getRenderType 的 TERRAIN、OPAQUE 和 TRANSLUCENT,它取代了这些。TERRAIN 和 TRANSLUCENT 都允许透明度,OPAQUE 和 TRANSLUCENT 从粒子图集拉取,而 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_SHEET、PAINTINGS_SHEET 和 GUI_SHEET。
从这些图集中获取 TextureAtlasSprite 现在完全通过 MaterialSet 路由:一个函数式接口,接受一个 Material(基本上是图集位置和纹理位置),并返回关联的 TextureAtlasSprite。MaterialSet 处理物品模型、方块实体渲染器和实体渲染器的纹理获取:
// 这是一个从适当图集中获取苹果纹理的材质示例
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/coreblit_screen.json->screenquad.json,使用无格式三角形而不是定位四边形position_color_lightmap.*已移除position_color_tex_lightmap.*已移除
com.mojang.blaze3d.vertexCompactVectorArray- 一个将浮点向量列表压缩到单个顺序数组中的持有者。MeshData$SortState#centroids现在返回一个CompactVectorArrayVertexSortingbyDistance现在接受一个Vector3fc而不是Vector3fsort现在接受一个CompactVectorArray而不是Vector3f[]
net.minecraft.client.MinecraftgetTextureAtlas->AtlasManager#getAtlasOrThrow,不是一对一getPaintingTextures、getMapDecorationTextures、getGuiSprites->getAtlasManager,不是一对一
net.minecraft.client.animation.Keyframe现在有一个重载,接受preTarget和postTarget而不是一个简单的target,接受Vector3fc而不是Vector3fnet.minecraft.client.entityClientAvatarEntity- 化身实体的客户端数据。ClientAvatarState- 化身的移动状态。ClientMannequin-Mannequin实体的客户端版本。
net.minecraft.client.guiGuiGraphicsrenderOutline->submitOutlinerenderDeferredTooltip->renderDeferredElements,不是一对一submitBannerPatternRenderState现在接受BannerFlagModel而不是ModelPartGuiSpriteManager类已移除
net.minecraft.client.gui.render.GuiRenderer现在接受SubmitNodeCollector和FeatureRenderDispatcherMIN_GUI_Z现在是公开的
net.minecraft.client.gui.render.pipGuiBannerResultRenderer现在接受一个MaterialSetGuiSignRenderer现在接受一个MaterialSet
net.minecraft.client.gui.render.state.TiledBlitRenderState- 一个用于使用平铺构建精灵的渲染状态,通常用于平铺或九切片纹理。net.minecraft.client.gui.render.state.pip.GuiBannerResultRenderState现在接受BannerFlagModel而不是ModelPartnet.minecraft.client.modelAbstractPiglinModel#createArmorMeshSet- 为每个人形盔甲槽位创建模型网格。ArmedModel现在有一个EntityRenderState的泛型translateToHand现在接受实体渲染状态
ArmorStandArmorModel#createBodyLayer->createArmorLayerSet,不是一对一BellModel$State- 表示支持对象的状态。BookModel$State- 表示支持对象的状态。BreezeModelcreateBodyLayer->createBaseMesh,现在是私有的- 被
createBodyLayer、createWindLayer、createEyesLayer取代
- 被
CopperGolemModel- 铜傀儡实体的模型。CopperGolemStatueModel- 铜傀儡雕像的模型。CreakingModelNO_PARTS、getHeadModelParts已移除createEyesLayer- 创建模型的眼睛。
EntityModel#setupAnim->Model#setupAnimGuardianParticleModel- 从守卫者生成的粒子。HeadedModel#translateToHead- 将姿势堆栈变换到头部的位置和旋转。HumanoidArmorModel->HumanoidModel#createArmorMeshSet,不是一对一HumanoidModel#copyPropertiesTo已移除Model现在接受一个表示渲染状态的泛型PlayerCapeModel现在继承PlayerModelPlayerEarsModel现在继承PlayerModelPlayerModel渲染状态已拓宽到AvatarRenderState- 静态字段现在是
protected createArmorMeshSet- 为每个人形盔甲槽位创建模型网格。
- 静态字段现在是
SkullModelBase$State- 表示支持对象的状态。SpinAttackEffectModel泛型已拓宽到AvatarRenderStateVillagerLikeModel现在接受渲染状态的泛型hatVisible已移除- 被
VillagerModel#createNoHatModel取代
- 被
translateToArms现在接受渲染状态
WardenModelcreateTendrilsLayer、createHeartLayer、createBioluminescentLayer、createPulsatingSpotsLayer- 创建监守者的RenderLayer使用的层。getTendrilsLayerModelParts、getHeartLayerModelParts、getBioluminescentLayerModelParts、getPulsatingSpotsLayerModelParts已移除
ZombieVillagerModelcreateArmorLayer->createArmorLayerSet,不是一对一createNoHatLayer- 创建没有帽子层的模型。
net.minecraft.client.model.geom.ModelPartcopyFrom已移除$Polygon#normal现在是Vector3fc而不是Vector3f$Vertexpos->x、y、zworldX、worldY、worldZ- 返回坐标缩小 16 倍后的值。
net.minecraft.client.model.geom.builders.PartDefinitionclearRecursively- 清除所有子部件及其子子部件。retainPartsAndChildren- 从其根和任何子子部件中保留指定的部件。retainExactParts- 仅保留顶级部件,清除所有其他部件和子子部件。
net.minecraft.client.particleAttackSweepParticle现在继承SingleQuadParticleBaseAshSmokeParticle现在继承SingleQuadParticle并且是abstractBlockMarker现在继承SingleQuadParticleBreakingItemParticle现在继承SingleQuadParticle- 构造函数接受
TextureAtlasSprite而不是ItemStackRenderState $ItemParticleProvider#calculateState->getSprite,不是一对一
- 构造函数接受
BubbleColumnUpParticle现在继承SingleQuadParticleBubbleParticle现在继承SingleQuadParticleBubblePopParticle现在继承SingleQuadParticleCampfireSmokeParticle现在继承SingleQuadParticleCritParticle现在继承SingleQuadParticleDragonBreathParticle现在继承SingleQuadParticle$Provider泛型现在使用PowerParticleOption
DripParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpritecreate*Particle方法 ->$*Provider类
DustParticleBase现在继承SingleQuadParticleElderGuardianParticleGroup- 负责设置和提交远古守卫者粒子的粒子组。ExplodeParticle现在继承SingleQuadParticleFallingDustParticle现在继承SingleQuadParticleFallingLeavesParticle现在继承SingleQuadParticle并接受TextureAtlasSprite而不是SpriteSetFireflyParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteFireworkParticles$FlashProvider泛型现在使用ColorParticleOption$OverlayParticle现在继承SingleQuadParticle并接受一个TextureAtlasSprite
FlameParticle现在接受一个TextureAtlasSpriteFlyStraightTowardsParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteFlyTowardsPositionParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteGlowParticle现在继承SingleQuadParticleGustParticle现在继承SingleQuadParticleHeartParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteHugeExplosionParticle现在继承SingleQuadParticleItemPickupParticle现在接受EntityRenderState而不是EntityRenderDispatcher- 除目标实体外,所有字段现在都是
protected
- 除目标实体外,所有字段现在都是
ItemPickupParticleGroup- 负责设置和提交物品拾取粒子的粒子组。LavaParticle现在继承SingleQuadParticleMobAppearanceParticle->ElderGuardianParticleNoRenderParticleGroup- 什么都不做的粒子组。NoteParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteParticlerCol、gCol、bCol、alpha->SingleQuadParticle#rCol、gCol、bCol、alpharoll、oRoll->SingleQuadParticle#roll、oRollsetColor、setAlpha->SingleQuadParticle#setColor、setAlpharender、renderCustom->ParticleGroupRenderState#submit,不是一对一getRenderType->getGroup- 此方法的原始用途已移至
SingleQuadParticle#getLayer
- 此方法的原始用途已移至
getParticleGroup->getParticleLimit,不是一对一
ParticleEngine不再实现PreparableReloadListener- 构造函数现在接受
ParticleResources而不是TextureManager close已移除updateCount现在是protectedrender->extract,不是一对一destroy->ClientLevel#addDestroyBlockEffectcrack->ClientLevel#addBreakingBlockEffectclearParticles现在是public$MutableSpriteSet->ParticleResources$MutableSpriteSet$SpriteParticleRegistration->ParticleResources$SpriteParticleRegistration
- 构造函数现在接受
ParticleGroup- 特定ParticleRenderType的粒子持有者,负责Tick和提取通用渲染状态。ParticleProvidercreateParticle现在接受RandomSource$Sprite#createParticle现在接受RandomSource并返回SingleQuadParticle而不是TextureSheetParticle
ParticleRenderType不再接受RenderType- 此记录已被重新用于表示粒子组的键
TERRAIN_SHEET->SingleQuadParticle$Layer#TERRAINPARTICLE_SHEET_OPAQUE->SingleQuadParticle$Layer#OPAQUEPARTICLE_SHEET_TRANSLUCENT->SingleQuadParticle$Layer#TRANSLUCENTCUSTOM被一个不是为ParticleRenderType#SINGLE_QUADS的粒子组取代
ParticleResources- 加载粒子提供者、任何必要的描述,并将它们计算到所需的精灵集中。PlayerCloudParticle现在继承SingleQuadParticlePortalParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteQuadParticleGroup- 负责设置和提交单个四边形粒子的粒子组。ReversePortalParticle现在接受一个TextureAtlasSpriteRisingParticle现在继承SingleQuadParticleSculkChargeParticle现在继承SingleQuadParticleSculkChargePopParticle现在继承SingleQuadParticleSculkChargePopParticle现在继承SingleQuadParticleShriekParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteSimpleAnimatedParticle现在继承SingleQuadParticle并且是abstractSingleQuadParticle现在接受一个TextureAtlasSpritesprite- 粒子的纹理。render->extract,不是一对一,现在接受QuadParticleRenderState而不是VertexConsumerrenderRotatedQuad->extractRotatedQuad,不是一对一,现在接受QuadParticleRenderState而不是VertexConsumergetU0、getU1、getV0、getV1不再是抽象的getLayer- 设置单个四边形的渲染层。$Layer- 单个四边形应渲染的层。
SnowflakeParticle现在继承SingleQuadParticleSpellParticle现在继承SingleQuadParticleInstantProvider泛型现在使用SpellParticleOption
SplashParticle现在接受一个TextureAtlasSpriteSpriteSet#first- 返回精灵集中的第一个纹理。SuspendedParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteSuspendedTownParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteTerrainParticle现在继承SingleQuadParticleTextureSheetParticle类已移除,请改用SingleQuadParticleTrailParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteTrialSpawnerDetectionParticle现在继承SingleQuadParticleVibrationSignalParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteWakeParticle现在继承SingleQuadParticleWaterCurrentDownParticle现在继承SingleQuadParticle并接受一个TextureAtlasSpriteWaterDropParticle现在继承SingleQuadParticle并接受一个TextureAtlasSprite
net.minecraft.client.player.AbstractClientPlayer字段现在存储在ClientAvatarState中elytraRot*->*CloakclientLevel已移除getDeltaMovementLerped->addWalkedDistance,不是一对一updateBob- 更新相机的摆动运动。
net.minecraft.client.rendererEndFlashState- 末地闪光的渲染状态。GameRenderer现在接受BlockRenderDispatchergetSubmitNodeStorage- 获取用于功能类对象的节点提交。getFeatureRenderDispatcher- 获取用于渲染功能类对象的分派器。getLevelRenderState- 获取等级中动态功能的渲染状态。
ItemInHandRendererrenderItem现在接受SubmitNodeCollector而不是MultiBufferSourcerenderHandsWithItems现在接受SubmitNodeCollector而不是MultiBufferSource$BufferSource
LevelRenderer现在接受LevelRenderState和FeatureRenderDispatchergetSectionRenderDispatcher现在可为 nulltickParticles已移除addParticle已移除
MapRenderer现在接受AtlasManager而不是MapDecorationTextureManagerrender现在接受SubmitNodeCollector而不是MultiBufferSource
OrderedSubmitNodeCollector- 一个提交处理器,用于在功能被分派时以给定顺序将元素绘制到屏幕。OutlineBufferSource不再接受任何参数setColor现在接受一个整数
ParticleGroupRenderState- 一组粒子的渲染状态。ParticlesRenderState- 所有粒子的渲染状态。QuadParticleRenderState- 所有单个四边形粒子的渲染组状态。RenderPipelinesGUI_TEXT- GUI 中文本的管线。GUI_TEXT_INTENSITY- GUI 中未着色文本的强度管线。
RenderStateShard#TRANSLUCENT_TARGET、PARTICLES_TARGET已移除RenderTypepipeline- 该类型使用的RenderPipeline。opaqueParticle、translucentParticle已移除sunriseSunset、celestial已移除
ScreenEffectRenderer现在接受一个MaterialSetrenderScreenEffect现在接受一个SubmitNodeCollector
ShapeRendererrenderLineBox现在接受PoseStack$Pose而不是PoseStackrenderFace现在接受Matrix4f而不是PoseStack
SheetsGUI_SHEET、MAP_DECORATIONS_SHEET、PAINTINGS_SHEET- 图集纹理。BLOCK_ENTITIES_MAPPER- 将方块纹理映射到方块实体的映射器。*COPPER*- 铜箱子的材质。chooseMaterial现在接受ChestRenderState$ChestMaterialType而不是BlockEntity和boolean
SkyRendererEND_SKY_LOCATION现在是私有的renderSunMoonAndStars不再接受缓冲区源renderEndFlash不再接受缓冲区源renderSunriseAndSunset不再接受缓冲区源
SpecialBlockModelRenderervanilla现在接受SpecialModelRenderer$BakingContext而不是EntityModelSetrenderByBlock现在接受SubmitNodeCollector而不是MultiBufferSource,以及一个轮廓颜色
SubmitNodeCollection-OrderedSubmitNodeCollector的一个实现,将提交的功能保存在单独的列表中。SubmitNodeCollector- 一个OrderedSubmitNodeCollector,提供更改元素将渲染的当前顺序的方法。SubmitNodeStorage- 由某个顺序持有的集合的存储。SkyRendererrenderEndFlash- 渲染末地闪光。initTextures- 获取所用元素的纹理。extractRenderState- 从当前等级提取SkyRenderState。
WeatherEffectRendererrender现在接受WeatherRenderState而不是int、float和Level- 这些字段已移至
extractRenderState
- 这些字段已移至
extractRenderState- 从当前等级提取WeatherRenderState。$ColumnInstance现在是公开的
WorldBorderRendererrender现在接受WorldBorderRenderState而不是WorldBorderextract- 从当前世界边界提取WorldBorderRenderState。
net.minecraft.client.renderer.blockBlockRenderDispatcher现在接受一个MaterialSetMovingBlockRenderState- 一个实现BlockAndTintGetter的移动方块的渲染状态。LiquidBlockRenderer#setupSprites现在接受BlockModelShaper和MaterialSet
net.minecraft.client.renderer.blockentity- 这里的大多数接受
MultiBufferSource的方法已被SubmitNodeCollector取代,如果该方法不用于物品渲染,则还有ModelFeatureRenderer$CrumblingOverlay - 大多数方法从
render*更名为submit*,主要的 submit 方法现在使用BlockEntityRenderState - 所有
BlockEntityRenderer现在都有一个BlockEntityRenderState泛型 AbstractEndPortalRenderer- 末地传送门的方块实体渲染器。AbstractSignRenderergetSignModel现在返回一个Model$SimplerenderSign->submitSign,现在接受一个Model$Simple并且不再接受色调颜色
BannerRenderer有一个接受SpecialModelRenderer$BakingContext的重载EntityModelSet构造函数现在接受MaterialSetrenderPatterns->submitPatterns现在接受MaterialSet和ModelFeatureRenderer$CrumblingOverlay,ModelPart已被Model及其渲染状态取代,一个boolean表示是否使用实体闪光,以及一个轮廓颜色- 带有两个额外
boolean的重载已移除
- 带有两个额外
renderSpecial->submitSpecial,现在接受轮廓颜色
BeaconRenderer#renderBeaconBeam->submitBeaconBeam,不再接受游戏时间longBedRenderer有一个接受SpecialModelRenderer$BakingContext的重载EntityModelSet构造函数现在接受MaterialSetrenderSpecial->submitSpecial,现在接受轮廓颜色
BlockEntityRenderDispatcher现在接受MaterialSet和PlayerSkinRenderCacherender->submit,现在接受BlockEntityRenderState而不是BlockEntity,不再接受部分刻float,并接受CameraRenderStategetRenderer现在有一个重载,可以从其BlockEntityRenderState获取渲染器tryExtractRenderState- 从BlockEntity获取BlockEntityRenderStatelevel、camera、cameraHitResult已移除prepare现在只接受CamerasetLevel已移除
BlockEntityRenderer现在有另一个泛型S表示BlockEntityRenderStaterender->submit,接受BlockEntityRenderState、PoseStack、SubmitNodeCollector和CameraRenderStatecreateRenderState- 创建渲染状态对象。extractRenderState- 从方块实体中提取渲染状态。
BlockEntityRendererProvider$Context现在是一个记录,接受MaterialSet和PlayerSkinRenderCache- 它现在有另一个泛型
S表示BlockEntityRenderState
- 它现在有另一个泛型
CopperGolemStatueBlockRenderer- 铜傀儡雕像的方块实体渲染器。DecoratedPotRenderer有一个接受SpecialModelRenderer$BakingContext的重载EntityModelSet构造函数现在接受MaterialSetrender重载 ->submit,现在接受轮廓颜色
HangingSignRenderercreateSignModel现在返回一个Model$SimplerenderInHand现在接受一个MaterialSet
ShelfRenderer- 架子的方块实体渲染器。ShulkerBoxRenderer有一个接受SpecialModelRenderer$BakingContext的重载EntityModelSet构造函数现在接受MaterialSetrender重载 ->submit,现在接受轮廓颜色
SignRenderercreateSignModel现在返回一个Model$SimplerenderInHand现在接受一个MaterialSet
SkullBlockRenderer#submitSkull- 将骷髅头模型提交给收集器。SpawnerRenderer#renderEntityInSpawner->submitEntityInSpawner,现在接受CameraRenderStateTestInstanceREnderer现在接受BlockEntityRendererProvider$Context
- 这里的大多数接受
net.minecraft.client.renderer.blockentity.stateBannerRenderState- 旗帜方块实体的渲染状态。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.Frustumoffset- 偏移位置。pointInFrustum- 检查提供的坐标是否在平截头体内。
net.minecraft.client.renderer.entity- 这里的大多数接受
MultiBufferSource和光照坐标整数的方法已被SubmitNodeCollector和渲染状态参数取代 - 大多数方法从
render*更名为submit* AbstractBoatRenderer#renderTypeAdditions->submitTypeAdditionsAbstractMinecartRenderer#renderMinecartContents->submitMinecartContentsAbstractSkeletonRenderer接受ArmorModelSet而不是ModelLayerLocationAbstractZombieRenderer接受ArmorModelSet而不是模型ArmorModelSet- 一个将某个对象映射到每个人形盔甲槽位的持有者。通常保存层定义,然后将其烘焙到关联的模型中。BreezeRenderer#enable已移除CopperGolemRenderer- 铜傀儡实体的渲染器。DisplayRenderer#renderInner->submitInnerEnderDragonRenderer#renderCrystalBeams->submitCrystalBeamsEntityRenderDispatcher现在接受AtlasManagerprepare不再接受LevelsetRenderShadow、setRenderHitBoxes、shouldRenderHitBoxes已移除extractEntity- 从实体和部分刻创建渲染状态。render->submit,现在接受CameraRenderStatesetLevel->resetCamera,不是一对一getPlayerRenderer- 从给定的客户端玩家获取AvatarRenderer。overrideCameraOrientation、distanceToSqr、cameraOrientation已移除
EntityRendererNAMETAG_SCALE现在是公开的render(S, PoseStack, MultiBufferSource, int)->submit(S, PoseStack, SubmitNodeCollector, CameraRenderState)renderNameTag->submitNameTag,现在接受CameraRenderStatefinalizeRenderState- 在extractRenderState之后作为最后一步提取渲染状态的信息,例如阴影。
EntityRendererProvider$Context现在接受PlayerSkinRenderCache和AtlasManagergetModelManager已移除getMaterials- 返回材质到图集精灵的映射器。getPlayerSkinRenderCache- 获取玩家皮肤的渲染缓存。getAtlas- 返回该位置的图集。
EntityRenderers#createPlayerRenderers现在返回一个PlayerModelType到AvatarRenderer的映射ItemEntityRendererrenderMultipleFromCount->submitMultipleFromCountrenderMultipleFromCount(PoseStack, MultiBufferSource, int, ItemClusterRenderState, RandomSource)->renderMultipleFromCount(PoseStack, SubmitNodeCollector, int, ItemClusterRenderState, RandomSource)
ItemRenderer不再接受ItemModelResolvergetArmorFoilBuffer->getFoilRenderTypes,不是一对一renderStatic方法已移除
MobRenderer#checkMagicName- 返回自定义名称是否与给定字符串匹配。PiglinRenderer接受ArmorModelSet而不是ModelLayerLocationTntMinecartRenderer#renderWhiteSolidBlock->submitWhiteSolidBlock,现在接受一个轮廓颜色ZombieRenderer接受ArmorModelSet而不是ModelLayerLocationZombifiedPiglinPiglinRenderer接受ArmorModelSet而不是ModelLayerLocation
- 这里的大多数接受
net.minecraft.client.renderer.entity.layersArrowLayer现在处理AvatarRenderState而不是PlayerRenderStateBeeStingerLayer现在处理AvatarRenderState而不是PlayerRenderStateBlockDecorationLayer- 一个处理由实体变换的方块模型的层。BreezeWindLayer现在接受EntityModelSet而不是EntityRendererProvider$ContextCapeLayer现在处理AvatarRenderState而不是PlayerRenderStateCustomHeadLayer现在接受PlayerSkinRenderCacheDeadmau5EarsLayer现在处理AvatarRenderState而不是PlayerRenderStateEquipmentLayerRenderer#renderLayers现在接受渲染状态、SubmitNodeCollector、轮廓颜色和一个初始顺序,而不是MultiBufferSourceHumanoidArmorLayer现在接受ArmorModelSet而不是模型setPartVisibility已移除
ItemInHandLayer#renderArmWithItem->submitArmWithItemLivingEntityEmissiveLayer现在接受一个用于纹理的函数而不是ResourceLocation,以及一个模型而不是$DrawSelector$DrawSelector已移除
ParrotOnShoulderLayer现在处理AvatarRenderState而不是PlayerRenderStatePlayerItemInHandLayer现在处理AvatarRenderState而不是PlayerRenderStateRenderLayerrenderColoredCutoutModel、coloredCutoutModelCopyLayerRender现在接受Model而不是EntityModel,接受SubmitNodeCollector而不是MultiBufferSource,以及一个表示渲染顺序的整数render->submit,接受SubmitNodeCollector而不是MultiBufferSource
SimpleEquipmentLayer现在接受一个顺序整数SpinAttackEffectLayer现在处理AvatarRenderState而不是PlayerRenderStateStuckInBodyLayer现在有一个用于渲染状态的额外泛型,在构造函数中也接受渲染状态numStuck现在接受AvatarRenderState而不是PlayerRenderState
VillagerProfessionLayer现在接受两个模型
net.minecraft.client.renderer.entity.player.PlayerRenderer->AvatarRendererrender*Hand现在接受SubmitNodeCollector而不是MultiBufferSource
net.minecraft.client.renderer.entity.stateCopperGolemRenderState- 铜傀儡实体的渲染状态。DisplayEntityRenderState#cameraYRot、cameraXRot- 相机的旋转。EntityRenderStateNO_OUTLINE- 一个表示无轮廓颜色的常量。outlineColor- 实体的轮廓颜色。lightCoords- 用于照亮实体的打包光照坐标。shadowPieces、$ShadowPiece- 表示实体投射的阴影的相对坐标。
FallingBlockRenderState字段和实现已全部移至MovingBlockRenderStateLivingEntityRenderStateappearsGlowing->EntityRenderState#appearsGlowing,现在是一个方法customName已移除
PaintingRenderState#lightCoords->lightCoordsPerBlockPlayerRenderState->AvatarRenderStateuseItemRemainingTicks、swinging已移除showDeadMouseEars->showExtraEars
SheepRenderStateid已移除isJebSheep现在是一个字段而不是方法
WitherSkullRenderState#xRot、yRot->modeState,不是一对一
net.minecraft.client.renderer.featureBlockFeatureRenderer- 渲染提交的方块、方块模型或下落中的方块。CustomFeatureRenderer- 通过传递的函数渲染提交的几何体。FeatureRenderDispatcher- 分派所有功能以从提交的节点收集器对象渲染。FlameFeatureRenderer- 渲染提交的着火的实体动画。HitboxFeatureRenderer- 渲染提交的实体碰撞箱。ItemFeatureRenderer- 渲染提交的物品。LeashFeatureRenderer- 渲染提交的附着在实体上的拴绳。ModelFeatureRenderer- 渲染提交的Model。ModelPartFeatureRenderer- 渲染提交的ModelPart。NameTagFeatureRenderer- 渲染提交的名称标签。ParticleFeatureRenderer- 渲染提交的粒子。ShadowFeatureRenderer- 渲染提交的实体阴影。TextFeatureRenderer- 渲染提交的文本。
net.minecraft.client.renderer.itemItemModel$BakingContext现在接受MaterialSet和PlayerSkinRenderCache,并实现SpecialModelRenderer$BakingContextItemStackRenderState#render->submit,接受SubmitNodeCollector而不是MultiBufferSource以及一个轮廓颜色
net.minecraft.client.renderer.special- 这里的大多数接受
MultiBufferSource的方法已被SubmitNodeCollector取代 ChestSpecialRenderer现在接受一个MaterialSet*COPPER*- 铜箱子的纹理。
ConduitSpecialRenderer现在接受一个MaterialSetCopperGolemStatueSpecialRenderer- 铜傀儡雕像作为物品的特殊渲染器。HangingSignSpecialRenderer现在接受一个MaterialSet和一个Model$Simple而不是ModelNoDataSpecialModelRenderer#render->submit,现在接受一个轮廓颜色PlayerHeadSpecialRenderer现在接受PlayerSkinRenderCacheShieldSpecialRenderer现在接受一个MaterialSetSpecialModelRendererrender->submit,现在接受一个轮廓颜色$BakingContext- 用于烘焙特殊物品模型的上下文。$Unbaked#bake现在接受SpecialModelRenderer$BakingContext而不是EntityModelSet
SpecialModelRenderers#createBlockRenderers现在接受SpecialModelRenderer$BakingContext而不是EntityModelSetStandingSignSpecialRenderer现在接受一个MaterialSet和一个Model$Simple而不是Model
- 这里的大多数接受
net.minecraft.client.renderer.stateBlockBreakingRenderState- 当前方块被破坏进度的渲染状态。BlockOutlineRenderState- 通过其VoxelShape的方块轮廓的渲染状态。CameraRenderState- 相机的渲染状态。LevelRenderState- 等级中动态功能的渲染状态。ParticleGroupRenderState- 一组粒子的渲染状态。ParticlesRenderState- 所有粒子的渲染状态。QuadParticleRenderState- 所有单个四边形粒子的渲染组状态。SkyRenderState- 天空的渲染状态,包括月亮和星星。WeatherRenderState- 当前天气的渲染状态。WorldBorderRenderState- 世界边界的渲染状态。
net.minecraft.client.renderer.textureSkinTextureDownloader现在是一个实例类而不是静态方法持有者,接受Proxy、TextureManager和主线程Executor- 以前是静态的大多数方法现在是实例方法
SpriteContents现在接受一个可选的AnimationMetadataSection和MetadataSectionType$WithValue列表,而不是ResourceMetadatametadata->getAdditionalMetadata,不是一对一
SpriteLoaderDEFAULT_METADATA_SECTIONS已移除stitch现在是私有的runSpriteSuppliers现在是私有的loadAndStitch(ResourceManager, ResourceLocation, int, Executor)已移除loadAndStitch现在接受一组MetadataSectionType而不是一个集合$PreparationswaitForUpload已移除getSprite- 返回给定资源位置的图集精灵。
TextureAtlasSprite#isAnimated->SpriteContents#isAnimated
net.minecraft.client.renderer.texture.atlas.SpriteResourceLoader#create现在接受一组MetadataSectionType而不是一个集合net.minecraft.client.resourcesMapDecorationTextureManager类已移除PaintingTextureManager类已移除PlayerSkin$Model->PlayerModelType,不是一对一- 构造函数现在接受遗留服务名称
byName->byLegacyServicesName
SkinManager现在接受Services而不是MinecraftSessionService,以及一个SkinTextureDownloaderlookupInsecure->createLookup,现在接受一个布尔值表示是否检查不安全的皮肤getOrLoad->get
TextureAtlasHolder类已移除
net.minecraft.client.resources.modelAtlasIds->net.minecraft.data.AtlasIdsAtlasSet->AtlasManager,不是一对一forEach- 遍历每个图集图版。
Materialsprite->MaterialSet#getbuffer现在接受一个MaterialSet
MaterialSet- 材质到其图集精灵的映射。ModelBakery现在接受MaterialSet和PlayerSkinRenderCacheModelManager不再是AutoCloseable- 构造函数接受
PlayerSkinRenderCache、AtlasManager而不是TextureManager,以及最大 mipmap 级别整数 getAtlas->MaterialSet#getupdateMaxMipLevel->AtlasManager#updateMaxMipLevel
- 构造函数接受
net.minecraft.core.particlesParticleGroup->ParticleLimitParticleTypesDRAGON_BREATH现在使用PowerParticleOptionEFFECT现在使用SpellParticleOptionFLASH现在使用ColorParticleOptionINSTANT_EFFECT现在使用SpellParticleOption
PowerParticleOption- 龙息粒子的粒子选项。SpellParticleOption- 药水效果的粒子选项。
字体 字形 管线
字形的后端已被部分重做,以将字符及其效果统一到一个可渲染的对象,并添加烘焙流程(尽管是延迟的)。本文将简要概述这个新流程。
让我们从资源重新加载时开始,导致 FontManager 运行。字体定义被加载并传递到它们适当的 GlyphProviderDefinition,对于这个例子,它将立即解包到 GlyphProvider$Loader 中。加载器读取它需要的任何信息(很可能是纹理),并将其映射到关联的码点作为 UnbakedGlyph。一个 UnbakedGlyph 表示一个包含其 GlyphInfo(带有位置元数据)的单个字符,以及一个将其写入纹理的 bake 方法。bake 接受一个 UnbakedGlyph$Stitcher,它本身接受一个 GlyphBitmap 以正确定位和上传字形,以及用于任何偏移调整的 GlyphInfo。然后,在解析和最终确定之后,使用 FontSet#reload 创建 FontSet。这会重置纹理和缓存,并调用 FontSet#selectProviders 来存储活动的 GlyphProvider 列表,并通过将字符宽度映射到匹配的码点列表来填充 glyphsByWidth。此时,所有加载都已完成。虽然字形以未烘焙的格式存储,但它们直到该特定字符被渲染时才被烘焙和缓存。
现在,让我们转到 FontDescription。FontDescription 提供了与 GlyphSource 的一对一映射,后者负责获取字形。原版提供了三种 FontDescription:$Resource 用于映射到如上所述的 FontSet(字体 JSON 名称),$AtlasSprite 用于将图集解释为一组字形,以及 $PlayerSprite 用于渲染玩家头部和帽子。对于给定的 Component,可以通过 Style#withFont 将使用的 FontDescription 设置为其 Style。
因此,假设您使用 FontDescription#DEFAULT 将文本绘制到屏幕,它使用定义的 assets/minecraft/font/default.json。最终,这将调用 Font#drawInBatch 或 drawInBatch8xOutline。然后,无论是通过 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.fontGlyphInfobake->UnbakedGlyph#bake,现在接受UnbakedGlyph$Stitcher而不是函数- 函数行为被
UnbakedGlyph$Stitcher#stitch取代
- 函数行为被
$SpaceGlyphInfo->GlyphInfo#simple和EmptyGlyph,不是一对一$Stitched->UnbakedGlyph,不是一对一
GlyphProvider#getGlyph现在返回一个UnbakedGlyphSheetGlyphInfo->GlyphBitmap
net.minecraft.client.guiFont不再接受函数和布尔值,而是接受Font$Providerrandom现在是私有的$GlyphVisitoracceptGlyph现在接受TextRenderable而不是BakedGlyph$GlyphInstanceacceptEffect现在只接受一个TextRenderable
$PreparedTextBuilder#accept现在有一个接受BakedGlyph而不是其码点的重载$Provider- 一个简单的接口,用于根据其描述提供字形源,以及空字形。
GlyphSource- 一个接口,根据其码点持有烘焙的字形。
net.minecraft.client.gui.fontAtlasGlyphProvider- 基于纹理图集的字形提供者。FontManager现在接受AtlasManager和PlayerSkinRenderCacheFontSet现在接受GlyphStitcher而不是TextureManager,并且不再接受名称name已移除source- 根据是否只应看到非可疑字形,返回字形源。getGlyphInfo、getGlyph->getGlyph,现在是包私有的,不是一对一getRandomGlyph现在接受RandomSource和一个码点而不是GlyphInfo,返回一个BakedGlyphwhiteGlyph现在返回一个EffectGlyph$GlyphSource- 一个可以获取要烘焙的字形的源。
FontTexture#add现在接受GlyphInfo和GlyphBitmap,返回一个BakedSheetGlyphGlyphStitcher- 一个从其字形信息创建BakedGlyph的类。PlainTextRenderable-TextRenderable的一个实现,确定如何渲染精灵。PlayerGlyphProvider- 用于渲染玩家头部和帽子的字形提供者。SingleSpriteSource- 一个只包含一个字形的字形源,例如一个纹理。TextRenderable- 表示文本表示(如字体中的字形)如何渲染。
net.minecraft.client.gui.font.glyphsBakedGlyph现在是一个创建可渲染对象的接口- 其原始用途已移至
BakedSheetGlyph
- 其原始用途已移至
EffectGlyph- 一个创建某个字形效果的可渲染对象的接口。EmptyGlyph现在实现UnbakedGlyph而不是继承BakedGlyph- 构造函数接受字形的文本宽度。
SpecialGlyphs#bake现在返回一个BakedSheetGlyph- 此方法在技术上是新的。
net.minecraft.client.gui.font.providersBitmapProvider$Glyph现在实现UnbakedGlyph而不是GlyphInfo$StitchedUnihexProvider$Glyph现在实现UnbakedGlyph而不是GlyphInfo$Stitched
net.minecraft.client.gui.render.stateGlyphEffectRenderState已移除- 使用
GlyphRenderState
- 使用
GlyphRenderState现在接受TextRenderable而不是BakedGlyph$Instance
net.minecraft.network.chatComponent#object- 创建一个带有对象内容的可变组件。ComponentContents#type->codec,丢弃字符串 id$Type已移除
ComponentSerializationcreateLegacyComponentMatcher不再需要StringRepresentable泛型,而是使用带有String键的 id 映射器$FuzzyCodec现在接受一组映射编解码器而不是一个列表
FontDescription- 一个描述字体的标识符,通常作为位置或精灵。Style现在是 finalgetFont现在返回一个FontDescriptionwithFont现在接受FontDescription而不是ResourceLocationDEFAULT_FONT已移除
net.minecraft.network.chat.contentsBlockDataSource->.data.BlockDataSourceDataSource->.data.DataSourcetype->codec,丢弃字符串 id
EntityDataSource->.data.EntityDataSource*ContentsCODEC->MAP_CODECTYPE已移除
ObjectContents- 可以作为组件一部分写入的任意内容,例如精灵。StorageDataSource->.data.StorageDataSource
net.minecraft.network.chat.contents.data.DataSources- 所有原版注册的数据源。net.minecraft.network.chat.contents.objectsAtlasSprite- 纹理图集中精灵的对象信息。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 中,该组件将引用名称映射到模式。然后可以通过 asRef 或 asArray 分别获取对象或数组实现。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#response 和 param 定义管理服务器发送的参数和响应。description 由发现服务用于模式。undiscoverable 默认隐藏路由。最后,notOnMainThread 告诉该方法它可以在主线程之外运行。一旦调用了所需的方法,就可以使用 build 或 register 来构造对象,接受路由端点的命名空间和路径。
传入的方法接受 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 通过 notification 或 request 构建器构造和注册。通知通常只发送参数而不返回结果,而请求也提供结果。在任何一种情况下,它们都只接受参数或结果(如果存在)的编解码器。$OutgoingRpcMethod#response 和 param 定义 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.registriesBuiltInRegistries、RegistriesINCOMING_RPC_METHOD- 对 RPC 服务的查询的注册表。OUTGOING_RPC_METHOD- 来自 RPC 服务的广播的注册表。
net.minecraft.serverMinecraftServernotificationManager- 返回当前通知管理器。onGameRuleChanged- 处理当前服务器的游戏规则更改时的情况。getOperatorUserPermissionLevel->operatorUserPermissionLevelisLevelEnabled->isAllowedToEnterPortal,不是一对一setPvpAllowed被GameRules#RULE_PVP取代setFlightAllowed被DedicatedServerProperties#allowFlight取代isCommandBlockEnabled不再是抽象的isSpawnerBlockEnabled- 返回刷怪笼方块是否可以生成实体。getPlayerIdleTimeout->playerIdleTimeoutkickUnlistedPlayers不再接受CommandSourceStackpauseWhileEmptySeconds->pauseWhenEmptySecondsgetSpawnProtectionRadius->DedicatedServer#spawnProtectionRadiusisUsingWhiteList- 处理为服务器启用白名单用户。setAutoSave、isAutoSave- 处理服务器是否应每隔一段时间自动保存。
net.minecraft.server.dedicatedDedicatedServer现在接受LevelLoadListener而不是ChunkProgressListenerFactorysetAllowFlight- 设置玩家是否可以在服务器中飞行。setDifficulty- 设置服务器的游戏难度。viewDistance、setViewDistance- 处理服务器的视距(可渲染区块)。simulationDistance、setSimulationDistance- 处理服务器的模拟距离(逻辑运行区块)。setMaxPlayers- 设置可以加入服务器的最大玩家数。setSpawnProtectionRadius- 设置应受重生保护保护的区块半径。setRepliesToStatus- 设置游戏是否使用旧式查询处理程序。setHidesOnlinePlayers- 设置是否应隐藏在线玩家不被其他玩家看到。setOperatorUserPermissionLevel- 设置操作员的权限级别。statusHeartbeatInterval、setStatusHeartbeatInterval- 处理管理服务器将检查 Minecraft 服务器是否仍然存活的心跳间隔。entityBroadcastRangePercentage、setEntityBroadcastRangePercentage- 处理实体跟踪的广播范围标量。forceGameMode、setForceGameMode- 处理强制所有用户的游戏模式。gameMode、setGameMode- 设置服务器的默认游戏模式。setAcceptsTransfers- 设置服务器是否接受来自其他服务器的客户端转移。setPauseWhenEmptySeconds- 设置当没有玩家时服务器应等待多少秒才停止Tick。
DedicatedServerPropertiespvp被GameRules#RULE_PVP取代allowFlight、motd、forceGameMode、enforceWhitelist、difficulty、gameMode、spawnProtection、opPermissionLevel、viewDistance、simulationDistance、enableStatus、hideOnlinePlayers、entityBroadcastRangePercentage、pauseWhenEmptySeconds、acceptsTransfers现在是可变属性allowNether被GameRules#RULE_ALLOW_NETHER取代spawnMonsters被GameRules#RULE_SPAWN_MONSTERS取代enabledCommandBlock被GameRules#RULE_COMMAND_BLOCKS_ENABLED取代managementServerEnabled- 返回是否启用了管理服务器。managementServerHost- 返回管理服务器通信的主机。managementServerPort- 返回管理服务器通信的端口。statusHeartbeatInterval- 返回管理服务器发送以确保 Minecraft 服务器仍然存活的心跳间隔。MANAGEMENT_SERVER_TLS_ENABLED_KEY、MANAGEMENT_SERVER_TLS_KEYSTORE_KEY、MANAGEMENT_SERVER_TLS_KEYSTORE_PASSWORD_KEY- 用于与管理服务器通信的 TLS 密钥库设置。managementServerSecret- 授权令牌密钥。managementServerTlsEnabled- 是否应使用 TLS 作为通信协议。managementServerTlsKeystore- 指定用于 TLS 密钥库的文件路径。managementServerTlsKeystorePassword- 指定密钥库文件的密码。
Settings#getMutable- 获取设置键和默认值的可变属性。
net.minecraft.server.jsonrpcConnection- 管理服务器发送的 json 元素的入站处理程序。IncomingRpcMethod- 管理服务器发送的传入消息的定义和处理程序。IncomingRpcMethods- 所有原版传入 RPC 处理程序。JsonRPCErrors- 一个枚举,包含尝试读取、解析或执行方法时可能抛出的错误。JsonRpcLogger- 一个用于 Minecraft 服务器执行的操作(无论是通信还是逻辑)的通用日志记录器。JsonRpcNotificationService- 一个向所有连接的 Minecraft 服务器广播的通知服务。JsonRPCUtils- 用于请求对象和错误的实用工具。ManagementServer- 一个用于 Minecraft 服务器与管理服务器通信的基本 websocket 通信。OutgoingRpcMethod- 对管理服务器的传出请求的定义和处理程序。OutgoingRpcMethods- 所有原版传出 RPC 处理程序。PendingRpcRequest- Minecraft 服务器向管理服务器发出的待处理请求。
net.minecraft.server.jsonrpc.apiMethodInfo- 定义由管理服务器处理的方法,无论是入站还是出站。ParamInfo- 定义特定方法接受的参数。PlayerDto- 表示玩家的数据传输对象。ReferenceUtil- 用于创建本地引用 URI 的实用工具。ResultInfo- 定义特定方法返回的响应。Schema- 用于发现服务、参数和结果的 JSON 模式的实现。SchemaComponent- 模式中某个组件的引用定义。
net.minecraft.server.jsonrpc.dataprovider.JsonRpcApiSchema- 一个从发现服务生成 JSON 模式的数据提供者。net.minecraft.server.jsonrpc.internalapiGameRules- 一个获取当前游戏规则值的 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.methodsAllowlistService- 一个处理来自管理服务器的关于允许列表的通信的服务。BanlistService- 一个处理来自管理服务器的关于玩家禁令列表的通信的服务。ClientInfo- 当前 Minecraft 服务器连接到管理服务器的标识符。DiscoveryService- 一个显示管理服务器支持的所有服务的模式的服务。EncodeJsonRpcException- 尝试编码 JSON 数据包时抛出的异常。GameRulesService- 一个处理来自管理服务器的关于游戏规则的通信的服务。IllegalMethodDefinitionException- 当提供的方法定义非法时抛出的异常。InvalidParameterJsonRpcException- 当方法的参数无效时抛出的异常。InvalidRequestJsonRpcException- 当请求无效时抛出的异常。IpBanlistService- 一个处理来自管理服务器的关于 IP 禁令列表的通信的服务。Message- 表示字面量或可翻译组件的数据传输对象。MethodNotFoundJsonRpcException- 当发生 404 错误时抛出的异常,表示方法不存在。OperatorService- 一个处理来自管理服务器的关于操作员命令的通信的服务。PlayerService- 一个处理来自管理服务器的关于玩家列表的通信的服务。RemoteRpcErrorException- 当管理服务器上出现问题时抛出的异常。ServerSettingsService- 一个处理来自管理服务器的关于服务器设置的通信的服务。ServerStateService- 一个处理来自管理服务器的关于当前服务器状态和发送消息的通信的服务。
net.minecraft.server.jsonrpc.securityAuthenticationHandler- 处理请求中认证令牌持有者的验证。JsonRpcSslContextProvider- 为 TLS 通信提供密钥库上下文。SecurityConfig- 处理密钥,从检查基本有效性到生成新密钥。
net.minecraft.server.jsonrpc.websocketJsonToWebSocketEncoder- 一个用于 JSON 的消息到消息编码器。WebSocketToJsonCodec- 一个用于 JSON 的消息到消息解码器。
net.minecraft.server.notificationsEmptyNotificationService- 一个什么都不做的通知服务。NotificationManager- 一个用于处理多个通知服务的管理器。NotificationService- 一个定义由监听器(如管理服务器)采取的预期操作的服务。
net.minecraft.server.playersBanListEntrygetReason现在可以为nullgetReasonMessage- 返回禁令原因的可翻译组件。
IpBanList现在接受NotificationServiceadd、remove- 处理列表中的条目。
PlayerList现在接受NotificationService而不是最大玩家数maxPlayers已移除op现在有一个用于权限级别和绕过限制布尔值的重载setUsingWhiteList->MinecraftServer#setUsingWhiteListgetPlayer- 通过名称获取玩家。
ServerOpList现在接受NotificationServiceadd、remove- 处理列表中的条目。
StoredUserEntry#getUser现在是公开的StoredUserList现在接受NotificationServiceadd、remove现在返回一个布尔值表示是否成功remove(StoredUserEntry<K>)已移除clear- 清除所有存储的用户。
UserBanList现在接受NotificationServiceadd、remove- 处理列表中的条目。
UserWhiteList现在接受NotificationServiceadd、remove- 处理列表中的条目。
输入处理整合
输入处理以前传递原始值,每个值都在自己单独的参数中,由 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.InputConstantsMOD_SHIFT、MOD_ALT、MOD_SUPER、MOD_CAPS_LOCK、MOD_NUM_LOCK- 用于转换键输入的修饰键。KEY_LWIN、KEY_RWIN->KEY_LSUPER、KEY_RSUPERgetKey现在接受KeyEvent而不是键和扫描码intisKeyDown、setupKeyboardCallbacks、setupMouseCallbacks、grabOrReleaseMouse、updateRawMouseInput现在接受Window而不是long句柄
net.minecraft.clientKeyboardHandlerkeyPress现在是私有的setup现在接受Window而不是long句柄
KeyMapping现在接受$Category而不是StringshouldSetOnIngameFocus- 返回键是否映射到键盘上的某个值。restoreToggleStatesOnScreenClosed- 将切换键恢复到游戏内操作期间的状态。key现在是 protectedrelease现在是 protectedCATEGORY_*->$Category#*- 可以通过
$Category#id获取键 - 组件可通过
$Category#label获得
- 可以通过
getCategory现在返回$Category而不是Stringmatches现在接受KeyEvent而不是键和扫描码intmatchesMouse现在接受MouseButtonEvent而不是按钮int
Minecraft#ON_OSX->InputQuirks#ON_OSXMouseHandler#setup现在接受Window而不是long句柄ToggleKeyMapping现在有一个接受输入类型的重载- 构造函数现在接受
KeyMapping$Category而不是String,以及一个boolean表示是否应恢复按键绑定的先前状态
- 构造函数现在接受
net.minecraft.client.gui.componentsAbstractButton#onPress现在接受InputWithModifiersAbstractScrollArea#updateScrolling现在接受MouseButtonEvent而不是按钮信息和 XY 位置AbstractWidgetonClick现在接受MouseButtonEvent而不是 XY 位置以及按钮是否被双击onRelease现在接受MouseButtonEvent而不是 XY 位置onDrag现在接受MouseButtonEvent而不是 XY 位置isValidClickButton现在接受MouseButtonInfo而不是按钮int
CommandSuggestionskeyPressed现在接受KeyEvent而不是键、扫描码、修饰符intmouseClicked现在接受MouseButtonEvent而不是按钮信息和 XY 位置$SuggestionsListmouseClicked不再接受按钮intkeyPressed现在接受KeyEvent而不是键、扫描码、修饰符int
MultilineTextField#keyPressed现在接受KeyEvent而不是键int
net.minecraft.client.gui.components.events.GuiEventListenerDOUBLE_CLICK_THRESHOLD_MS->MouseHandler#DOUBLE_CLICK_THRESHOLD_MSmouseClicked现在接受MouseButtonEvent而不是按钮信息和 XY 位置,以及按钮是否被双击mouseReleased现在接受MouseButtonEvent而不是按钮信息和 XY 位置mouseDragged现在接受MouseButtonEvent而不是按钮信息和 XY 位置keyPressed现在接受KeyEvent而不是键、扫描码、修饰符intkeyReleased现在接受KeyEvent而不是键、扫描码、修饰符intcharTyped现在接受CharacterEvent而不是码点char和修饰符int
net.minecraft.client.gui.font.TextFieldHelpercharTyped现在接受CharacterEvent而不是码点charkeyPressed现在接受KeyEvent而不是键int
net.minecraft.client.gui.navigation.CommonInputs类已移除selected->InputWithModifiers#isSelectionconfirm->InputWithModifiers#isConfirmation
net.minecraft.client.gui.screens.ScreenhasControlDown->Minecraft#hasControlDown、InputWithModifiers#hasControlDownhasShiftDown->Minecraft#hasShiftDown、InputWithModifiers#hasShiftDownhasAltDown->Minecraft#hasAltDown、InputWithModifiers#hasAltDownisCut->InputWithModifiers#isCutisPaste->InputWithModifiers#isPasteisCopy->InputWithModifiers#isCopyisSelectAll->InputWithModifiers#isSelectAll
net.minecraft.client.gui.screens.inventory.AbstractContainerScreenhasClickedOutside不再接受按钮intcheckHotbarKeyPressed现在接受KeyEvent而不是键和修饰符int
net.minecraft.client.gui.screens.options.controls.KeyBindsList$CategoryEntry现在接受KeyMapping$Category而不是Componentnet.minecraft.client.gui.screens.recipebookhasClickedOutside不再接受按钮intRecipeBookPage#mouseClicked现在接受MouseButtonEvent而不是按钮信息和 XY 位置,以及按钮是否被双击
net.minecraft.client.inputCharacterEvent- 某种输入交互生成一个码点,带有当前活动的修饰符。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而不是LivingEntitynet.minecraft.client.renderer.itemItemModel#update现在接受ItemOwner而不是LivingEntityItemModelResolver#updateForTopItem、appendItemLayers现在接受ItemOwner而不是LivingEntity
net.minecraft.client.renderer.item.properties.numericNeedleDirectionHelper#get、calculate现在接受ItemOwner而不是LivingEntityRangeSelectItemModelProperty#get现在接受ItemOwner而不是LivingEntityTime$TimeSource#get现在接受ItemOwner而不是Entity
net.minecraft.world.entityEntity现在实现ItemOwnerItemOwner- 表示正在渲染的物品的拥有者。
容器使用者
由于 Minecraft 的这个新版本引入了铜傀儡(一种可以与库存交互的原版生物),可以使用容器的实体的概念已被抽象为其自己的接口:ContainerUser。ContainerUser 预计将在某个 LivingEntity 子类上实现。由于实际的库存逻辑在其他地方处理,ContainerUser 只有两个方法:hasContainerOpen,检查活体实体当前是否正在打开某个容器(例如,桶、箱子);以及 getContainerInteractionRange,确定实体可以与某个容器交互的半径(以方块为单位)。
net.minecraft.world.ContainerstartOpen、stopOpen现在接受ContainerUser而不是PlayergetEntitiesWithContainerOpen- 返回正在与此容器交互的ContainerUser列表。
net.minecraft.world.entity.ContainerUser- 通常是可以与容器交互并打开容器的实体。net.minecraft.world.entity.player.Player现在实现ContainerUsernet.minecraft.world.level.block.entity.EnderChestBlockEntity#startOpen、stopOpen现在接受ContainerUser而不是Player
名称和 ID
除非需要 GameProfile,否则 Minecraft 现在为每个玩家传递一个 NameAndId。顾名思义,NameAndId 包含玩家的 UUID 和名称,因为对于涉及玩家实体的大多数逻辑来说,这通常就是全部所需。
net.minecraft.commands.arguments.GameProfileArgumentgetGameProfiles现在返回NameAndId的集合$Result#getNames现在返回NameAndId的集合
net.minecraft.network.codec.ByteBufCodecs#PLAYER_NAME- 玩家名称的 16 字节字符串流编解码器。net.minecraft.network.protocol.status.ServerStatus$Players#Sample现在是一个NameAndId列表,而不是GameProfilenet.minecraft.serverMinecraftServergetProfilePermissions现在接受NameAndId而不是GameProfileisSingleplayerOwner现在接受NameAndId而不是GameProfileANONYMOUS_PLAYER_PROFILE现在是一个NameAndId
Services现在接受UserNameToIdResolver而不是GameProfileCache,以及一个ProfileResolver
net.minecraft.server.playersGameProfileCache->UserNameToIdResolver、CachedUserNameToIdResolver;不是一对一getAsync已移除add(GameProfile)已移除
NameAndId- 一个包含配置文件的 UUID 和名称的对象。PlayerListload->loadPlayerData,不是一对一canPlayerLogin现在接受NameAndId而不是GameProfiledisconnectAllPlayersWithProfile现在接受UUID而不是GameProfileop、deop现在接受NameAndId而不是GameProfileisWhiteListed、isOp现在接受NameAndId而不是GameProfilecanBypassPlayerLimit现在接受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 更改为类型安全的变体 TypedEntityData。TypedEntityData 与 CustomData 几乎相同,存储一个 CompoundTag,不同之处在于它由某个 IdType 泛型(如 EntityType 或 BlockEntityType)表示。CustomData 中与方块实体和实体相关的所有方法都已移至 TypedEntityData。
刷怪蛋使用 TypedEntityData 来存储它将生成的 EntityType。生成的逻辑仍然与 SpawnEggItem 子类绑定。
net.minecraft.core.component.DataComponents#ENTITY_DATA、BLOCK_ENTITY_DATA现在是带有EntityType和BlockEntityTypeid 的TypeEntityDatanet.minecraft.world.entity.EntityType#updateCustomEntityTag现在接受TypedEntityData而不是CustomDatanet.minecraft.world.item.Item$Properties#spawnEgg- 添加带有实体类型的ENTITY_DATA组件。net.minecraft.world.item.componentCustomDataCODEC_WITH_ID已移除COMPOUND_TAG_CODEC- 用于扁平复合标签的编解码器。parseEntityId、parseEntityType已移除loadInto->TypedEntityData#loadIntoupdate、read、size已移除contains->TypedEntityData#containsgetUnsafe->TypedEntityData#getUnsafe
TypedEntityData- 一个提供类型安全标识符的自定义数据。
net.minecraft.world.level.Spawner#appendHoverText、getSpawnEntityDisplayName现在接受TypedEntityData而不是CustomDatanet.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.resourcesPreparableReloadListenerreload现在接受PreparableReloadListener$SharedState而不是ResourceManagerprepareSharedState- 在重载监听器重新加载之前调用的方法,用于在重载监听器之间共享数据。$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_PERSIST、persist取代了布尔值FLAG_LOADING取代了$TicketUse#LOADINGFLAG_SIMULATION取代了$TicketUse#SIMULATIONFLAG_KEEP_DIMENSION_ACTIVE、shouldKeepDimensionActive- 设置后,防止等级卸载。FLAG_CAN_EXPIRE_IF_UNLOADED、canExpireIfUnloaded- 设置后,如果区块被卸载,加载票将过期。START->PLAYER_SPAWN、SPAWN_SEARCH$TicketUse类已移除
net.minecraft.world.level.TicketStorageshouldKeepDimensionActive- 检查存储中是否有任何加载票设置了维度活动标志。removeTicketIf现在接受$TicketPredicate而不是BiPredicate$TicketPredicate- 测试给定区块位置的加载票。
重生数据
重生逻辑已被整合到一个称为 LevelData$RespawnData 的单一对象中。重生数据保存全局位置(等级键和方块位置)以及实体的旋转。所有对原始角度和位置方法的调用已被 Level#setRespawnData 或 getRespawnData 取代,后者委托给 MinecraftServer 并最终委托给等级数据。
net.minecraft.client.multiplayer.ClientLevel#setDefaultSpawnPos->Level#setRespawnDatanet.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket现在是一个记录- 参数已被一个
LevelData$RespawnData对象取代
- 参数已被一个
net.minecraft.server.MinecraftServerfindRespawnDimension- 获取玩家应重生的默认ServerLevel。setRespawnData- 设置默认重生位置。getRespawnData- 获取默认重生位置。
net.minecraft.server.levelServerLevel#setDefaultSpawnPos->Level#setRespawnDataServerPlayer$RespawnConfig现在接受LevelData$RespawnData而不是维度、位置和角度- 字段仍然可以从重生数据访问
net.minecraft.world.level.Level#getSharedSpawnPos、getSharedSpawnAngle->getRespawnData、getWorldBorderAdjustedRespawnData,不是一对一net.minecraft.world.level.storageLevelDatagetSpawnPos、getSpawnAngle->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作为背景,而不是ClientAssetnet.miencraft.client.renderer.texture.SkinTextureDownloader#downloadAndRegisterSkin现在返回ClientAsset$Texture的 future,而不是ResourceLocationnet.minecraft.client.resourcesPlayerSkin->net.minecraft.world.entity.player.PlayerSkin- 构造函数现在接受
ClientAsset$Texture而不是ResourceLocation和String texture、textureUrl->bodycapeTexture->capeelytraTexture->elytrainsecure- 构造一个insecure设置为 false 的PlayerSkin。with- 从其$Patch构建PlayerSkin。$Patch- 一个打包对象,表示在其他文件或通过网络发送时的皮肤。
- 构造函数现在接受
SkinManager$TextureCache#getOrLoad现在返回ClientAsset$Texture的 future,而不是ResourceLocation
net.minecraft.core.ClientAsset现在是一个接口而不是记录- 原始实现移至
$ResourceTexture id仍然作为一个方法存在texturePath->$Texture#texturePathCODEC、DEFAULT_FIELD_CODEC、STREAM_CODEC->$ResourceTexture#*$DownloadedTexture- 从互联网下载的纹理。$Texture- 定义一个纹理的客户端资源。
- 原始实现移至
net.minecraft.world.entity.animal.CatVariant#assetInfo现在接受ClientAsset$ResourceTexture而不是ClientAssetnet.minecraft.world.entity.animal.frog.FrogVariant#assetInfo现在接受ClientAsset$ResourceTexture而不是ClientAssetnet.minecraft.world.entity.animal.wolf.WolfVariant$AssetInfo#*现在接受ClientAsset$ResourceTexture而不是ClientAssetnet.minecraft.world.entity.variant.ModelAndTexture#asset现在接受ClientAsset$ResourceTexture而不是ClientAsset
光标类型
屏幕上的当前光标现在可以通过 GUI 中的 GuiGraphics#requestCursor 或任何其他地方的 Window#selectCursor 更改为本机 CursorType,通过 GLFW#glfwCreateStandardCursor。注意 Window#setAllowCursorChanges 必须为 true,这可以通过选项菜单设置。
com.mojang.blaze3d.platform.WindowsetAllowCursorChanges- 设置光标是否可以更改为不同的标准形状。selectCursor- 将当前光标设置为指定类型。
com.mojang.blaze3d.platform.cursorCursorType- GLFW 标准光标形状的定义。createStandardCursor- 从其形状、名称和后备创建标准光标。
CursorTypes- Blaze3d 的光标类型。
net.minecraft.client.Options#allowCursorChanges- 设置光标是否可以更改为不同的标准形状。net.minecraft.client.gui.GuiGraphicsrequestCursor- 请求光标提交以进行渲染。applyCursor- 应用光标更改以进行渲染。
新标签
minecraft:blockwooden_shelvescopper_chestslightning_rodscoppercopper_golem_statuesincorrect_for_copper_toolchainslanternsbars
minecraft:entity_typescannot_be_pushed_onto_boatsaccepts_iron_golem_giftcandidate_for_iron_golem_gift
minecraft:itemwooden_shelvescopper_chestslightning_rodscoppercopper_golem_statuescopper_tool_materialsrepairs_copper_armorchainslanternsbarsshearable_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_MINOR、DATA_PACK_FORMAT_MINOR- 资源包版本的次要组件。net.minecraft.advancements.critereon.MinMaxBoundsbounds- 返回值的边界。$FloatDegrees- 表示某个角度的浮点数的边界。
net.minecraft.clientMinecraftisOfflineDevelopedMode- 返回游戏是否处于离线开发者模式。canSwitchGameMode- 玩家实体是否存在并具有游戏模式。playerSkinRenderCache- 返回持有玩家渲染纹理的缓存。canInterruptScreen- 当前屏幕是否可以被另一个屏幕关闭。packetProcessor- 返回调度和处理数据包的处理器。
OptionsinvertMouseX- 当为 true 时,反转 X 轴鼠标移动。toggleAttack- 当为 true 时,将攻击键设置为可切换。toggleUse- 当为 true 时,将使用键设置为可切换。sprintWindow- 双击前进键激活疾跑的时间窗口(以刻为单位)。saveChatDrafts- 返回如果输入框关闭,正在聊天中键入的消息是否应保留。keySpectatorHotbar- 调出旁观者快捷栏菜单的键。
ToggleKeyMapping#shouldRestoreStateOnScreenClosed- 屏幕关闭后是否应恢复先前的切换状态。
net.minecraft.client.animation.definitions.CopperGolemAnimation- 铜傀儡的动画。net.minecraft.client.data.models.BlockModelGeneratorsand- 将给定的条件进行 AND 运算。createShelf- 从基础纹理和粒子纹理创建一个架子方块状态。addShelfPart- 为架子的所有状态添加一个模型的变体。forEachHorizontalDirection- 对一对方向和旋转执行操作。shelfCondition- 基于架子的状态构造一个条件。createCopperGolemStatues- 创建所有铜傀儡雕像。createCopperGolemStatue- 为提供的方块、铜块和锈蚀状态创建一个铜傀儡雕像。createCopperChests- 创建所有铜箱子。createCopperLantern- 创建一个灯笼和悬挂式灯笼。createCopperChain- 创建一个链。createCopperChainItem- 创建一个链物品模型。
net.minecraft.client.data.models.modelModelTemplateSHELF_*- 用于将架子构建为多部分的模型模板。LIGHTNING_ROD- 避雷针的模型模板。CHAIN- 链的模型模板。BARS_*- 用于构建类似栏杆方块的模型模板。
TexturedModel#CHAIN- 链的模型提供者。TextureMapping#bars- 类似栏杆方块的纹理映射。TextureSlot#BARS- 对#bars纹理的引用。
net.minecraft.client.guiGui#renderDeferredSubtitles- 在屏幕上渲染字幕。GuiGraphics#getSprite- 从其材质获取TextureAtlasSprite。
net.minecraft.client.gui.componentsAbstractScrollArea#isOverScrollbar- 返回当前光标位置是否在滚动条上。AbstractSelectionListsort- 对列表中的条目进行排序。swap- 交换列表中两个条目的位置clearEntriesExcept- 移除所有与提供的元素不匹配的条目。getNextY- 返回渲染滚动组件的 Y 分量。entriesCanBeSelected- 列表中的条目是否可以被选择。scrollToEntry- 滚动条,使选中的条目显示在屏幕上。removeEntries- 移除提供的列表中的所有条目。$Entryset*- 设置组件大小。getContent*- 获取内容大小和位置。
ChatComponentsaveAsDraft、discardDraft- 处理聊天框中的草稿消息。createScreen、openScreen、preserveCurrentChatScreen、restoreChatScreen- 根据草稿聊天选项处理屏幕行为。$ChatMethod- 定义聊天的消息类型。$Draft- 定义聊天框中的草稿消息。
EditBoxDEFAULT_HINT_STYLE- 默认提示的样式。SEARCH_HINT_STYLE- 可搜索提示的样式,例如配方书中的提示。$TextFormatter- 用于格式化框中字符串的接口。
FittingMultiLineTextWidget#minimizeHeight- 将小部件的高度设置为内部高度和内边距。FocusableTextWidget$BackgroundFill- 一个枚举,表示何时应填充背景。ItemDisplayWidget#renderTooltip- 提交要渲染的工具提示。MultiLineLabel$Align- 处理标签的对齐方式。MultilineTextField#selectWordAtCursor- 选择光标当前所在的单词。SpriteIconButton$Builder#withTooltip- 设置显示消息的工具提示。StringWidgetsetMaxWidth- 设置字符串的最大宽度以及如何处理多余的宽度。$TextOverflow- 如果文本长于最大宽度,则采取的操作。
net.minecraft.client.gui.components.events.GuiEventListener#shouldTakeFocusAfterInteraction- 当为 true 时,在点击时将元素设置为焦点。net.minecraft.client.gui.screensChatScreenisDraft- 框中是否有未发送的消息。exitReason- 聊天屏幕被关闭的原因。shouldDiscardDraft- 是否应丢弃当前的草稿消息。$ChatConstructor- 基于草稿状态的聊天屏幕的构造函数。$ExitReason- 聊天屏幕被关闭的原因。
FaviconTexture#isClosed- 返回纹理是否已关闭。LevelLoadingScreenupdate- 更新当前加载跟踪器和原因。$Reason- 更改等级加载屏幕的原因。
Overlay#tick- Tick覆盖层。ScreenpanoramaShouldSpin- 返回渲染的全景图是否应旋转其相机。setNarrationSuppressTime- 设置旁白应被抑制到什么时间。isInGameUi- 返回屏幕是否在游戏进行中(而不是暂停菜单)打开。isAllowedInPortal- 此屏幕是否可以在传送门过渡效果期间打开。canInterruptWithAnotherScreen- 此屏幕是否可以被另一个屏幕关闭,默认为“按 Esc 关闭”屏幕。
net.minecraft.client.gui.screens.inventory.AbstractCommandBlockScreen#addExtraControls- 向命令方块屏幕添加任何额外的小部件。net.minecraft.client.gui.screens.multiplayerCodeOfConductScreen- 一个显示服务器的行为准则文本的屏幕。ServerSelectionList$Entrymatches- 返回提供的条目是否与此条目匹配。join- 处理客户端如何加入服务器条目。
net.minecraft.client.gui.screens.reporting.ChatSelectionScreen$ChatSelectionList#ITEM_HEIGHT- 列表中每个条目的高度。net.minecraft.client.gui.screens.worldselection.WorldSelectionListreturnToScreen- 重新加载世界列表后返回上一个屏幕。$Builder- 创建一个新的WorldSelectionList。$Entry#getLevelSummary- 返回所选世界的摘要。$EntryType- 一个枚举,表示条目的世界类型。$NoWorldsEntry- 一个没有世界可供选择的条目。
net.minecraft.client.main.GameConfig$GameData#offlineDeveloperMode- 游戏是否离线并用于开发。net.minecraft.client.multiplayerClientCommonPacketListenerImplseenPlayers- 该玩家看到的所有玩家,无论他们当前是否在线。seenInsecureChatWarning- 玩家是否已看到不安全聊天警告。$CommonDialogAccess- 客户端网络使用的对话框访问。
ClientConfigurationPacketListenerImpl#DISCONNECTED_MESSAGE- 因不接受行为准则而断开连接时显示的消息。ClientExplosionTracker- 跟踪客户端上发生的爆炸,专门用于处理粒子。ClientLevelendFlashState- 处理末地中出现的闪光状态。trackExplosionEffects- 跟踪爆炸以处理其粒子。
ClientPacketListenergetSeenPlayers- 返回该玩家看到的所有玩家。getPlayerInfoIgnoreCase- 获取提供的配置文件名称的玩家信息。
net.minecraft.client.player.LocalPlayerResolver- 本地玩家的配置文件解析器。net.minecraft.client.resources.WaypointStyle#ICON_LOCATION_PREFIX- 路径点图标的前缀。net.minecraft.client.server.IntegratedServer#MAX_PLAYERS- 本地托管服务器允许的最大玩家数。net.minecraft.client.soundsDirectionalSoundInstance- 一个根据相机方向改变位置的声音。SoundEngineExecutor#startUp- 创建运行引擎的线程。SoundPreviewHandler- 一个用于预览某个事件在给定设置下听起来如何的实用工具。
net.minecraft.coreBlockPos#betweenCornersInDirection- 一个可迭代对象,按向量提供的方向遍历提供的边界。Direction#axisStepOrder- 返回应检查给定向量的方向列表。
net.minecraft.core.particles.ExplosionParticleInfo- 用作爆炸一部分的粒子。net.minecraft.data.loot.BlockLootSubProvider#createCopperGolemStatueBlock- 铜傀儡雕像的战利品表。net.minecraft.data.loot.packsVanillaBlockInteractLoot- 来自实体交互的原版方块战利品的子提供者。VanillaChargedCreeperExplosionLoot- 来自闪电苦力怕爆炸的原版实体战利品的子提供者。VanillaEntityInteractLoot- 来自实体交互的原版实体战利品的子提供者。
net.minecraft.data.recipes.RecipeProvider#shelf- 从一个物品构造一个架子配方。net.minecraft.data.worldgen.BiomeDefaultFeatures#addNearWaterVegetation- 在水体附近添加植被。net.minecraft.gametest.framework.GameTestHelper#getTestDirection- 获取测试面向的方向。net.minecraft.networkFriendlyByteBuf#readLpVec3、writeLpVec3- 处理同步压缩的Vec3。LpVec3- 一个 vec3 网络处理程序,将向量压缩和解压缩为最多两个字节和两个整数。PacketProcessor- 用于调度和处理数据包的处理器。
net.minecraft.network.chat.CommonComponents#GUI_COPY_TO_CLIPBOARD- 将聊天复制到剪贴板时显示的消息。net.minecraft.network.protocol.configurationClientboundCodeOfConductPacket- 一个将服务器的行为准则发送给加入客户端的数据包。ClientConfigurationPacketListener#handleCodeOfConduct- 处理从服务器发送的行为准则。ServerboundAcceptCodeOfConductPacket- 一个发送客户端从服务器读取行为准则的接受响应的数据包。ServerConfigurationPacketListener#handleAcceptCodeOfConduct- 处理来自客户端的行为准则接受。
net.minecraft.network.syncher.EntityDataSerializersWEATHERING_COPPER_STATE- 傀儡上铜的风化状态。COPPER_GOLEM_STATE- 铜傀儡的逻辑状态。RESOLVABLE_PROFILE- 实体的可解析配置文件。
net.minecraft.server.MinecraftServerselectLevelLoadFocusPos- 返回服务器的加载中心位置,通常是共享重生位置。getLevelLoadListener- 返回用于跟踪等级加载的监听器。getCodeOfConducts- 返回文件名到其行为准则文本的映射。enforceGameTypeForPlayers- 设置所有玩家的游戏类型。packetProcessor- 返回服务器的数据包处理器。
net.minecraft.server.commands.FetchProfileCommand- 获取给定用户的配置文件。net.minecraft.server.dedicated.DedicatedServerProperties#codeOfConduct- 服务器是否有行为准则。net.minecraft.server.levelChunkLoadCounter- 在等级加载或玩家生成时跟踪区块加载。ChunkMapgetLatestStatus- 返回给定区块位置的最新状态。isTrackedByAnyPlayer- 检查实体是否被任何玩家跟踪。forEachEntityTrackedBy- 遍历给定玩家跟踪的每个实体。forEachReadyToSendChunk- 遍历每个准备好发送给客户端的区块。
ServerChunkCachehasActiveTickets- 检查当前等级是否有任何保持其加载的活动加载票。addTicketAndLoadWithRadius- 向某个位置添加加载票,并加载该位置及其半径内的区块。
ServerEntity$Synchronizer- 处理向跟踪实体发送数据包。ServerLevel#isSpawningMonsters- 返回服务器是否可以生成怪物。ServerPlayer$SavedPosition- 保存玩家在磁盘上的当前位置。
net.minecraft.server.level.progress.ChunkLoadStatusView- 加载区块的状态视图。net.minecraft.server.network.ConfigurationTask#tick- 每刻调用该任务,直到返回 true,然后完成任务。net.minecraft.server.network.configPrepareSpawnTask- 一个查找玩家生成点的配置任务。ServerCodeOfConductConfigurationTask- 一个将行为准则发送给客户端的配置任务。
net.minecraft.server.packs.OverlayMetadataSectioncodecForPackType- 根据资源包类型为部分构造一个编解码器。forPackType- 从资源包类型获取元数据部分类型。
net.minecraft.server.packs.metadata.MetadataSectionType#withValue、$WithValue- 持有元数据部分及其提供的值。net.minecraft.server.packs.metadata.packPackFormat- 表示资源包的主要和次要修订版本。PackMetadataSection#forPackType- 从资源包类型获取元数据部分类型。
net.minecraft.server.packs.repository.PackCompatibility#UNKNOWN- 资源包与游戏的兼容性未知,因为主要版本设置为最大整数值。net.minecraft.server.packs.resources.ResourceMetadata#getTypedSection、getTypedSections- 获取提供的类型的元数据部分。net.minecraft.server.players.ProfileResolver- 从其名称或 UUID 解析游戏配置文件。net.minecraft.utilExtraCodecsgameProfileCodec- 给定 UUID 编解码器,为GameProfile创建一个编解码器。$LateBoundIdMapper#values- 返回映射器内的值集合。
InclusiveRange#map- 将一个泛型的范围映射到另一个泛型。Mth#ceilLong- 返回向上取整到最近长整型的双精度值。
net.minecraft.util.randomWeighted#streamCodec- 为加权条目构造一个流编解码器。WeightedList#streamCodec- 为加权列表构造一个流编解码器。
net.minecraft.util.thread.BlockableEventLoop#shouldRunAllTasks- 返回是否有任何阻塞的任务。net.minecraft.world.Nameable#getPlainTextName- 返回名称组件的字符串。net.minecraft.world.entityAvatar- 一个构成玩家基础的实体。EntityReferencegetEntity- 根据类型类和等级返回实体。- 静态
getEntity、getLivingEntity、getPlayer- 根据其EntityReference和等级返回实体。
EntityTypeMANNEQUIN- 人体模型实体类型。STREAM_CODEC- 实体类型的流编解码器。$Builder#notInPeaceful- 设置实体不在和平模式下生成。
EntitycanInteractWithLevel- 实体是否可以与当前等级交互。isInShallowWater- 返回玩家是否在水中但未在水下。getAvailableSpaceBelow- 返回实体与碰撞体之间在 Y 方向上的空间量,按给定值偏移。collectAllColliders- 返回所有实体碰撞。
InsideBlockEffectType#CLEAR_FREEZE- 一个清除冰冻刻数的方块内效果。LivingEntitydropFromEntityInteractLootTable- 从实体交互的战利品表中掉落战利品。shouldTakeDrowningDamage- 实体是否应受到溺水伤害。
Mob#WEARING_ARMOR_UPGRADE_MATERIAL_CHANCE、WEARING_ARMOR_UPGRADE_MATERIAL_ATTEMPTS- 盔甲材料升级的常量。PositionMoveRotation#withRotation- 使用提供的 XY 旋转创建一个新对象。Relativerotation- 从 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.MemoryModuleTypeVISITED_BLOCK_POSITIONS- 访问过的重要方块位置。TRANSPORT_ITEMS_COOLDOWN_TICKS- 在运输物品之前等待多少刻。UNREACHABLE_TRANSPORT_BLOCK_POSITIONS- 保存一个无法到达的位置列表。
net.minecraft.world.entity.ai.navigation.GroundPathNavigation#setCanPathToTargetsBelowSurface- 设置实体是否可以将起始位置下方非空气方块下方的其他实体作为目标。net.minecraft.world.entity.animal.coppergolemCopperGolem- 铜傀儡实体。CopperGolemAi- 铜傀儡的大脑逻辑。CopperGolemOxidationLevel- 一个记录,保存给定氧化等级的源事件和纹理。CopperGolemOxidationLevels- 所有原版氧化等级。CopperGolemState- 铜傀儡所处的当前逻辑状态。
net.minecraft.world.entity.decorationHangingEntity#canCoexist- 是否有任何其他悬挂实体与此实体位于同一位置。默认情况下,确保实体不是相同的实体类型且不面向相同的方向。Mannequin- 一个没有连接玩家的人体模型。
net.minecraft.world.entity.playerPlayerisMobilityRestricted- 返回玩家是否有失明效果。handleShoulderEntities- 处理玩家肩膀上的实体。extractParrotVariant、convertParrotVariant、*ShoulderParrot*- 处理玩家肩膀上的鹦鹉。
PlayerModelPart#CODEC- 模型部件的编解码器。
net.minecraft.world.entity.raid.Raids#getRaidCentersInChunk- 返回给定区块中的袭击中心数量。net.minecraft.world.entity.vehicle.MinecartFurnace#addFuel- 向熔炉添加燃料以推动实体。net.minecraft.world.itemBucketItem#getContent- 返回桶中持有的流体。Item$TooltipContext#isPeaceful- 如果难度设置为和平,则返回 true。ToolMaterial#COPPER- 铜工具材料。WeatheringCopperItems- 一个记录,表示每个风化铜状态的物品。
net.minecraft.world.item.equipmentArmorMaterials#COPPER- 铜盔甲材料。EquipmentAssets#COPPER- 铜装备资源的键引用。ResolvableProfileskinPatch- 返回玩家皮肤引用。$Static- 使用已解析的游戏配置文件。$Dynamic- 在使用时动态解析游戏配置文件。$Partial- 根据提供给组件的任何信息表示游戏配置文件的一部分。
net.minecraft.world.levelBaseCommandBlock$CloseableCommandBlockSource- 通常用于命令方块的命令源。ChunkPos#contains- 给定的方块位置是否在区块中。GameRules#RULE_SPAWNER_BLOCKS_ENABLED- 刷怪笼方块是否应生成实体。LevelgetEntityInAnyDimension- 通过 UUID 获取实体。getPlayerInAnyDimension- 通过 UUID 获取玩家。hasEntities- 返回提供的边界是否具有匹配类型和谓词的实体。palettedContainerFactory- 返回用于创建调色板容器的工厂。
net.minecraft.world.level.border.WorldBorder$Settings#toWorldBorder- 从设置构造世界边界。net.minecraft.world.level.blockBlock#dropFromBlockInteractLootTable- 与方块交互时掉落战利品。ChestBlockchestCanConnectTo- 返回箱子是否可以与另一个方块合并。getConnectedBlockPos- 获取箱子的连接方块位置。getOpenChestSound、getCloseChestSound- 返回箱子打开/关闭时播放的声音。getChestType- 根据周围的箱子返回箱子的类型。
ChiseledBookShelfBlock#FACING、SLOT_*_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 的版本更新日志 中找到它们的列表。
重命名混乱
许多核心类、方法和参数被重新组织和重命名,同时保留了它们各自的功能。以下是最重要变更的列表。
ResourceLocation 到 Identifier
所有对 ResourceLocation 的引用,无论是在方法名称、参数还是其他类中,都已替换为 Identifier。
util 包
大多数工具类已移至 net.minecraft.util。这些需要重新导入。
critereon 到 criterion
net.minecraft.advancements.critereon 已重命名为 net.minecraft.advancements.criterion。这些需要重新导入。
实体和对象子包
net.minecraft.client.model 和 net.minecraft.world.entity 都已根据支持对象的类型重新组织为额外的子包。这些需要重新导入。
net.minecraftBlockUtil->.util.BlockUtilFileUtil->.util.FileUtilResourceLocationException->IdentifierExceptionUtil->.util.Util
net.minecraft.advancements.critereon->.advancements.criterionnet.minecraft.client.gui.screens.inventory.JigsawBlockEditScreen#isValidResourceLocation->isValidIdentifiernet.minecraft.client.modelAbstractBoatModel->.object.boat.AbstractBoatModelAbstractEquineModel->.animal.equine.AbstractEquineModelAbstractPiglinModel->.monster.piglin.AbstractPiglinModelAbstractZombieModel->.monster.zombie.AbstractZombieModelAllayModel->.animal.allay.AllayModelArmadilloModel->.animal.armadillo.ArmadilloModelArmorStandArmorModel->.object.armorstand.ArmorStandArmorModelArmorStandModel->.object.armorstand.ArmorStandModelArrowModel->.object.projectile.ArrowModelAxolotlModel->.animal.axolotl.AxolotlModelBannerFlagModel->.object.banner.BannerFlagModelBannerModel->.object.banner.BannerModelBatModel->.ambient.BatModelBeeModel->.animal.bee.BeeModelBeeStingerModel->.animal.bee.BeeStingerModelBellModel->.object.bell.BellModelBlazeModel->.monster.blaze.BlazeModelBoatModel->.object.boat.BoatModelBoggedModel->.monster.skeleton.BoggedModelBookModel->.object.book.BookModelBreezeModel->.monster.breeze.BreezeModelCamelModel->.animal.camel.CamelModelCamelSaddleModel->.animal.camel.CamelSaddleModelCatModel->.animal.feline.CatModelChestModel->.object.chest.ChestModelChickenModel->.animal.chicken.ChickenModelCodModel->.animal.fish.CodModelColdChickenModel->.animal.chicken.ColdChickenModelColdCowModel->.animal.cow.ColdCowModelColdPigModel->.animal.pig.ColdPigModelCopperGolemModel->.animal.golem.CopperGolemModelCopperGolemStatueModel->.object.statue.CopperGolemStatueModelCowModel->.animal.cow.CowModelCreakingModel->.monster.creaking.CreakingModelCreeperModel->.monster.creeper.CreeperModelDolphinModel->.animal.dolphin.DolphinModelDonkeyModel->.animal.equine.DonkeyModelDrownedModel->.monster.zombie.DrownedModelElytraModel->.object.equipment.ElytraModelEndCrystalModel->.object.crystal.EndCrystalModelEndermanModel->.monster.enderman.EndermanModelEndermiteModel->.monster.endermite.EndermiteModelEquineSaddleModel->.animal.equine.EquineSaddleModelEvokerFangsModel->.effects.EvokerFangsModelFelineModel->.animal.feline.FelineModelFoxModel->.animal.fox.FoxModelFrogModel->.animal.frog.FrogModelGhastModel->.monster.ghast.GhastModelGiantZombieModel->.monster.zombie.GiantZombieModelGoatModel->.animal.goat.GoatModelGuardianModel->.monster.guardian.GuardianModelGuardianParticleModel->.monster.guardian.GuardianParticleModelHappyGhastHarnessModel->.animal.ghast.HappyGhastHarnessModelHappyGhastModel->.animal.ghast.HappyGhastModelHoglinModel->.monster.hoglin.HoglinModelHorseModel->.animal.equine.HorseModelIllagerModel->.monster.illager.IllagerModelIronGolemModel->.animal.golem.IronGolemModelLavaSlimeModel->.monster.slime.MagmaCubeModelLeashKnotModel->.object.leash.LeashKnotModelLlamaModel->.animal.llama.LlamaModelLlamaSpitModel->.animal.llama.LlamaSpitModelMinecartModel->.object.cart.MinecartModelOcelotModel->.animal.feline.OcelotModelPandaModel->.animal.panda.PandaModelParrotModel->.animal.parrot.ParrotModelPhantomModel->.monster.phantom.PhantomModelPiglinHeadModel->.object.skull.PiglinHeadModelPiglinModel->.monster.piglin.PiglinModelPigModel->.animal.pig.PigModelPlayerCapeModel->.player.PlayerCapeModelPlayerEarsModel->.player.PlayerEarsModelPlayerModel->.player.PlayerModelPolarBearModel->.animal.polarbear.PolarBearModelPufferfishBigModel->.animal.fish.PufferfishBigModelPufferfishMidModel->.animal.fish.PufferfishMidModelPufferfishSmallModel->.animal.fish.PufferfishSmallModelRabbitModel->.animal.rabbit.RabbitModelRaftModel->.object.boat.RaftModelRavagerModel->.monster.ravager.RavagerModelSalmonModel->.animal.fish.SalmonModelSheepFurModel->.animal.sheep.SheepFurModelSheepModel->.animal.sheep.SheepModelShieldModel->.object.equipment.ShieldModelShulkerBulletModel->.object.projectile.ShulkerBulletModelShulkerModel->.monster.shulker.ShulkerModelSilverfishModel->.monster.silverfish.SilverfishModelSkeletonModel->.monster.skeleton.SkeletonModelSkullModel->.object.skull.SkullModelSkullModelBase->.object.skull.SkullModelBaseSlimeModel->.monster.slime.SlimeModelSnifferModel->.animal.sniffer.SnifferModelSnowGolemModel->.animal.golem.SnowGolemModelSpiderModel->.monster.spider.SpiderModelSpinAttackEffectModel->.effects.SpinAttackEffectModelSquidModel->.animal.squid.SquidModelStriderModel->.monster.strider.StriderModelTadpoleModel->.animal.frog.TadpoleModelTridentModel->.object.projectile.TridentModelTropicalFishModelA->.animal.fish.TropicalFishSmallModelTropicalFishModelB->.animal.fish.TropicalFishLargeModelTurtleModel->.animal.turtle.TurtleModelVexModel->.monster.vex.VexModelVillagerModel->.npc.VillagerModelWardenModel->.monster.warden.WardenModelWarmCowModel->.animal.cow.WarmCowModelWindChargeModel->.object.projectile.WindChargeModelWitchModel->.monster.witch.WitchModelWitherBossModel->.monster.wither.WitherBossModelWolfModel->.animal.wolf.WolfModelZombieModel->.monster.zombie.ZombieModelZombieVillagerModel->.monster.zombie.ZombieVillagerModelZombifiedPiglinModel->.monster.piglin.ZombifiedPiglinModel
net.minecraft.client.model.dragonDragonHeadModel->.model.object.skull.DragonHeadModelEnderDragonModel->.model.monster.dragon.EnderDragonModel
net.minecraft.client.resources.soundsAbstractSoundInstance#location->identifierSoundInstance#getLocation->getIdentifier
net.minecraft.client.searchtreeIdSearchTreeresourceLocationSearchTree->identifierSearchTreesearchResourceLocation->searchIdentifier
ResourceLocationSearchTree->IdentifierSearchTree
net.minecraft.commands.arguments.ResourceLocationArgument->IdentifierArgumentnet.minecraft.network.FriendlyByteBuf#readResourceLocation,writeResourceLocation->readIdentifier,writeIdentifiernet.minecraft.resourcesResourceKey#location->identifierResourceLocation->Identifier
net.minecraft.util.ResourceLocationPattern->IdentifierPatternnet.minecraft.util.parsing.packrat.commands.ResourceLocationParseRule->IdentifierParseRulenet.minecraft.world.entity.GlowSquid->.animal.squid.GlowSquidnet.minecraft.world.entity.animalAbstractCow->.cow.AbstractCowAbstractFish->.fish.AbstractFishAbstractGolem->.golem.AbstractGolemAbstractSchoolingFish->.fish.AbstractSchoolingFishBee->.bee.BeeCat->.feline.CatCatVariant->.feline.CatVariantCatVariants->.feline.CatVariantsChicken->.chicken.ChickenChickenVariant->.chicken.ChickenVariantChickenVariants->.chicken.ChickenVariantsCod->.fish.CodCow->.cow.CowCowVariant->.cow.CowVariantCowVariants->.cow.CowVariantsDolphin->.dolphin.DolphinFox->.fox.FoxHappyGhast->.happyghast.HappyGhastHappyGhastAi->.happyghast.HappyGhastAiIronGolem->.golem.IronGolemMushroomCow->.cow.MushroomCowOcelot->.feline.OcelotPanda->.panda.PandaParrot->.parrot.ParrotPig->.pig.PigPigVariant->.pig.PigVariantPigVariants->.pig.PigVariantsPolarBear->.polarbear.PolarBearPufferfish->.fish.PufferfishRabbit->.rabbit.RabbitSalmon->.fish.SalmonShoulderRidingEntity->.parrot.ShoulderRidingEntitySnowGolem->.golem.SnowGolemSquid->.squid.SquidTropicalFish->.fish.TropicalFishTurtle->.turtle.TurtleWaterAnimal->.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.EnderDragonPartnet.minecraft.world.entity.decorationPainting->.painting.PaintingPaintingVariant->.painting.PaintingVariantPaintingVariants->.painting.PaintingVariants
net.minecraft.world.entity.monsterAbstractIllager->.illager.AbstractIllagerAbstractSkeleton->.skeleton.AbstractSkeletonBogged->.skeleton.BoggedCaveSpider->.spider.CaveSpiderDrowned->.zombie.DrownedEvoker->.illager.EvokerHusk->.zombie.HuskIllusioner->.illager.IllusionerParched->.skeleton.ParachedPillager->.illager.PillagerSkeleton->.skeleton.SkeletonSpellcasterIllager->.illager.SpellcasterIllagerSpider->.spider.SpiderStray->.skeleton.StrayVindicator->.illager.VindicatorWitherSkeleton->.skeleton.WitherSkeletonZombie->.zombie.ZombieZombieVillager->.zombie.ZombieVillagerZombifiedPiglin->.zombie.ZombifiedPiglin
net.minecraft.world.entity.npcAbstractVillager->.villager.AbstractVillagerVillager->.villager.VillagerVillagerData->.villager.VillagerDataVillagerDataHolder->.villager.VillagerDataHolderVillagerProfession->.villager.VillagerProfessionVillagerTrades->.villager.VillagerTradesVillagerType->.villager.VillagerTypeWanderingTrader->.wanderingtrader.WanderingTraderWanderingTraderSpawner->.wanderingtrader.WanderingTraderSpawner
net.minecraft.world.entity.projectileAbstractArrow->.arrow.AbstractArrowAbstractHurtingProjectile->.hurtingprojectile.AbstractHurtingProjectileAbstractThrownPotion->.throwableitemprojectile.AbstractThrownPotionArrow->.arrow.ArrowDragonFireball->.hurtingprojectile.DragonFireballFireball->.hurtingprojectile.FireballLargeFireball->.hurtingprojectile.LargeFireballSmallFireball->.hurtingprojectile.SmallFireballSnowball->.throwableitemprojectile.SnowballSpectralArrow->.arrow.SpectralArrowThrowableItemProjectile->.throwableitemprojectile.ThrowableItemProjectileThrownEgg->.throwableitemprojectile.ThrownEggThrownEnderpearl->.throwableitemprojectile.ThrownEnderpearlThrownExperienceBottle->.throwableitemprojectile.ThrownExperienceBottleThrownLingeringPotion->.throwableitemprojectile.ThrownLingeringPotionThrownSplashPotion->.throwableitemprojectile.ThrownSplashPotionThrownTrident->.arrow.ThrownTridentWitherSkull->.hurtingprojectile.WitherSkull
net.minecraft.world.entity.projectile.windcharge.*->.projectile.hurtingprojectile.windcharge.*net.minecraft.world.entity.vehicleAbstractBoat->.boat.AbstractBoatAbstractChestBoat->.boat.AbstractChestBoatAbstractMinecart->.minecart.AbstractMinecartAbstractMinecartContainer->.minecart.AbstractMinecartContainerBoat->.boat.BoatChestBoat->.boat.ChestBoatChestRaft->.boat.ChestRaftMinecart->.minecart.MinecartMinecartBehavior->.minecart.MinecartBehaviorMinecartChest->.minecart.MinecartChestMinecartCommandBlock->.minecart.MinecartCommandBlockMinecartFurnace->.minecart.MinecartFurnaceMinecartHopper->.minecart.MinecartHopperMinecartSpawner->.minecart.MinecartSpawnerMinecartTNT->.minecart.MinecartTNTNewMinecartBehavior->.minecart.NewMinecartBehaviorOldMinecartBehavior->.minecart.OldMinecartBehaviorRaft->.boat.Raft
net.minecraft.world.level.gamerules.GameRule#getResourceLocation->getIdentifier
哦,又来了,一次渲染重写
渲染管线的更多部分已被重写,主要集中在采样器、RenderType 的创建和 mipmap 上。
采样器的分离
Blaze3d 已将读取纹理数据时的 AddressMode 和 FilterMode 设置分离到 GpuSampler 中。顾名思义,GpuSampler 定义了如何从缓冲区(如纹理)采样数据。GpuSampler 包含四个方法:getAddressModeU / getAddressModeV 用于确定采样器在读取 UV 位置时的行为(重复或钳位),getMinFilter / getMagFilter 用于分别确定如何缩小或放大纹理(最近邻或线性),getMaxAnisotropy 用于可用的最大各向异性过滤级别,以及 getMaxLod 用于纹理的最大细节级别。
采样器可以通过 GpuDevice#createSampler 创建,但除非您想指定大于 1 的不同各向异性过滤级别,或者最大细节级别不是 0 或 1000,否则没有必要。由于只有 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#draw 将 MeshData 写入输出目标。
Mipmap 策略元数据
纹理的 mcmeta 现在可以在 textures 部分中指定要使用的 mipmap_strategy。有四种可用的策略,auto 在没有透明度时默认为 mean,在有透明度时默认为 cutout。
| 策略 | 描述 |
|---|---|
mean | 默认策略,对当前 mipmap 级别的四个像素之间的颜色进行平均。 |
cutout | 与 mean 相同,但所有级别都是从原始纹理生成的,使用 0.2 的阈值将 alpha 捕捉到 0 或 1。 |
strict_cutout | 与 cutout 相同,但使用 0.6 的阈值设置 alpha 捕捉。 |
dark_cutout | 与 mean 相同,但仅当周围像素的 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.buffersGpuBuffer,size现在使用long作为大小slice现在使用long作为长度和偏移
GpuBufferSlice现在使用long作为长度和偏移
com.mojang.blaze3d.openglBufferStoragecreateBuffer现在使用long作为大小mapBuffer现在使用long作为长度和偏移
DirectStateAccessbufferSubData现在使用long作为偏移mapBufferRange、flushMappedBufferRange、copyBufferSubData现在使用long作为长度和偏移
GlBuffer现在使用long作为大小GlDevice现在接受ShaderSource而不是BiFunctiongetOrCompileShader现在接受ShaderSource而不是BiFunction
GlRenderPasssamplers现在是一个字符串到GlRenderPass$TextureViewAndSampler的哈希映射$TextureViewAndSampler- 一个记录,定义了一个采样器及其采样的纹理。
GlSampler- GPU 采样器的 OpenGL 实现。GlStateManager_glBufferSubData现在使用long作为偏移_glMapBufferRange现在使用long作为长度和偏移
GlTexture#modesDirty、flushModeChanges已移除GlTextureView#getFbo- 获取纹理的帧缓冲区对象,如果存在则使用缓存。
com.mojang.blaze3d.pipeline.RenderTarget#filterMode、setFilterMode已移除com.mojang.blaze3d.platform.TextureUtilsolidify- 通过打包和解包像素来修改纹理,以更好地帮助 mipmap 内的非暗化内部。fillEmptyAreasWithDarkColor- 将空像素设置为一个 RGB 值为图像中最暗颜色的空像素。
com.mojang.blaze3d.shaders.ShaderSource- 一个函数式接口,从其 id 和类型以字符串形式获取着色器源。com.mojang.blaze3d.systemsCommandEncoder#copyTextureToBuffer现在使用long作为偏移GpuDevicecreateSampler- 为某个源到目标创建一个采样器,具有所需的地址和过滤模式。precompilePipeline现在接受ShaderSource而不是BiFunctiongetMaxSupportedAnisotropy- 硬件支持的最大各向异性过滤级别。createBuffer现在使用long作为大小
RenderPass#bindTexture现在接受GpuSamplerRenderSystem现在使用long作为大小samplerCache- 返回一个包含所有可能组合的采样器缓存。TEXTURE_COUNT已移除setupOverlayColor、teardownOverlayColor已移除setShaderTexture、getShaderTexture已移除setTextureMatrix、resetTextureMatrix、getTextureMatrix已移除lineWidth->VertexConsumer#setLineWidthgetShaderLineWidth->Window#getAppropriateLineWidthinitRenderer现在接受ShaderSource而不是BiFunction
SamplerCache- 一个缓存,包含渲染器可能使用的所有采样器。
com.mojang.blaze3d.texturesGpuSampler- 一个具有指定 UV 地址模式和缩小及放大过滤器的缓冲区采样器。GpuTextureaddressModeU->GpuSampler#getAddressModeUaddressModeV->GpuSampler#getAddressModeVminFilter->GpuSampler#getMinFiltermagFilter->GpuSampler#getMagFiltersetAddressMode、setTextureFilter已被SamplerCache#getSampler取代,不是一对一useMipmaps、setUseMipmaps已移除
net.minecraft.clientOptions#textureFiltering- 从一定角度或远处观看时选择的纹理采样方法。TextureFilteringMethod- 从一定角度或远处观看纹理时的采样方法。
net.minecraft.client.gui.render.TextureSetup现在接受每个纹理的GpuSampler- 这也包括静态构造函数
net.minecraft.client.particle.SingleQuadParticle$Layer#ITEMS- 用于具有物品纹理的粒子的层。net.minecraft.client.rendererFaceInfo$Constants->$Extent$VertexInfo现在是一个记录
ItemBlockRenderTypes#getRenderType(ItemStack)LightTexture#turnOffLightLayer、turnOnLightLayer已移除LevelRenderer#resetSampler- 重置区块层采样器。PostPass$Input#bilinear- 是否使用双线性过滤器。$TextureInput现在接受一个boolean,表示是否使用双线性过滤器
RenderPipelinesSOLID->SOLID_BLOCK、SOLID_TERRAINCUTOUT->CUTOUT_BLOCK、CUTOUT_TERRAINCUTOUT_MIPPED已移除TRANSLUCENT->TRANSLUCENT_TERRAINTRIPWIRE->TRIPWIRE_BLOCK、TRIPWIRE_TERRAINANIMATE_SPRITE_SNIPPET、ANIMATE_SPRITE_BLIT、ANIMATE_SPRITE_INTERPOLATION- 用于动画精灵的管线。
RenderStateShard已被RenderSetup取代,不是一对一$LightmapStateShard->RenderSetup#useLightmap$OverlayStateShard->RenderSetup#useOverlay$MultiTextureStateShard、$TextureStateShard->RenderSetup#textures$LayeringStateShard->RenderSetup#layeringTransform、LayeringTransform$LineStateShard->VertexConsumer#setLineWidth$OutputStateShard->RenderSetup#outputTarget、OutputTarget$TexturingStateShard、$OffsetTexturingStateShard->RenderSetup#textureTransform、TextureTransform
RenderType已被拆分为两个独立的概念,不是一对一- 所有存储的
RenderType已移至RenderTypes - 实际的类用法已移至
.rendertype.RenderType,在那里它执行$CompositeRenderType的工作
- 所有存储的
Sheets#translucentBlockItemSheet- 用于半透明方块物品的渲染类型。
net.minecraft.client.renderer.blockBlockRenderDispatcher不再接受提供的SpecialBlockModelRendererLiquidBlockRenderer现在接受MaterialSetsetupSprites已移至LiquidBlockRenderer构造函数中
net.minecraft.client.renderer.block.modelBakedQuadvertices->position*、packedUV*,不是一对一position- 根据索引获取位置向量。packedUV- 根据索引获取打包的 UV。
BlockElementRotation现在接受Vector3fc作为原点,以及Matrix4fc变换- 构造函数也接受
$RotationValue而不是Direction$Axis和角度float $EulerXYZRotation- 以度为单位的 XYZ 旋转。$RotationValue- 一个定义旋转变换的接口。$SingleAxisRotation- 围绕单个轴以度为单位的旋转。
- 构造函数也接受
FaceBakeryVERTEX_COUNT->BakedQuad#VERTEX_COUNTVERTEX_INT_SIZE、COLOR_INDEX、UV_INDEX已移除bakeQuad现在接受ModelBaker$PartCacheextractPositions已移除
SimpleModelWrapper#bake现在返回BlockModelPartSimpleUnbakedGeometry#bake现在接受ModelBaker而不是SpriteGetterTextureSlots$parseTextureMap不再接受IdentifierVariantwithZRot- 围绕 Z 轴旋转模型状态。$SimpleModelState现在接受一个 ZQuadrantwithZ- 设置模型状态的 Z 象限。
VariantMutator#Z_ROT- 围绕 Z 轴旋转模型。
net.minecraft.client.renderer.chunkChunkSectionLayer不再接受是否使用 mipmapCUTOUT_MIPPED已移除texture已移除
ChunkSectionsToRender现在接受GpuTextureViewdynamicTransforms->chunkSectionInfosrenderGroup现在接受GpuSampler
net.minecraft.client.renderer.itemBlockModelWrapper构造函数现在是包私有的computeExtents现在返回Vector3fc的数组
ItemStackRenderState$LayerRenderStateNO_EXTENTS_SUPPLIER现在是一个提供的Vector3fc数组setExtents现在接受一个提供的Vector3fc数组
net.minecraft.client.renderer.rendertype.RenderTypesMOVING_BLOCK_SAMPLER- 用于移动中方块的采样器。solid->solidMovingBlockcutout->cutoutMovingBlocktripwire->tripwireMovingBlock
net.minecraft.client.renderer.textureAbstractTexture#setUseMipmaps已移除MipmapGenerator#generateMipLevels现在接受纹理的名称、一个MipmapStrategy来确定特定纹理应如何进行 mipmap,以及一个用于 alpha 截止偏置的floatMipmapStrategy- 一个枚举,定义了在为纹理构造 mipmap 时使用的策略。OverlayTexture#setupOverlayColor、teardownOverlayColor被getTextureView取代,不是一对一SpriteContents现在接受一个可选的TextureMetadataSection来确定精灵的元数据UBO_SIZE- 精灵内容的统一缓冲区对象大小。createTicker->createAnimationState,不是一对一uploadFirstFrame不再接受纹理int,而是接受一个 mip 级别int$AnimatedTexture#createTicker、uploadFirstFrame->createAnimationState,不是一对一$Ticker->$AnimationState,不是一对一tickAndUpload->tick、getDrawUbo、needsToDraw、drawToAtlas;不是一对一
SpriteTicker接口已移除Stitcher现在接受各向异性过滤级别$Holder(T, int)已移除$Region#walk现在接受一个填充int$SpriteLoader不再接受最小宽度/高度load现在接受一个填充int
TextureAtlas现在实现TickableTexture而不是TickableTextureAtlasSprite现在实现AutoCloseable- 构造函数接受一个填充
int createTicker->createAnimationState,不是一对一getUOffset、getVOffset、uvShrinkRatio已移除uploadFirstFrame现在接受 mip 级别intuploadSpriteUbo- 将图集精灵上传到缓冲区。$Ticker接口已移除
- 构造函数接受一个填充
TextureManager不再实现TickableTickable->TickableTexture
net.minecraft.client.renderer.texture.atlasSpriteSource$SpriteSupplier->$DiscardableLoaderFunction超接口现在表示为$Loaderapply->get
SpriteSourceList#list现在返回一个SpriteSource$Loader列表
net.minecraft.client.resources.metadata.texture.TextureMetadataSection现在接受一个MipmapStrategy来确定特定纹理应如何进行 mipmap,以及一个用于 alpha 截止偏置的floatnet.minecraft.client.resources.modelModelBakermissingBlockModelPart- 缺失的方块模型。parts- 先前构造的向量的缓存。$PartCache- 一个缓存,用于内部存储四边形中先前构造的顶点。
ModelBakery*_STILL- 流体的静态纹理位置。$MissingModels现在接受一个BlockModelPart缺失模型
ModelManagerBLOCK_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 不是 NOOP。GizmoProperties 提供了三个方法:
| 方法 | 描述 |
|---|---|
setAlwaysOnTop | 在渲染前清除深度纹理。 |
persistForMillis | 在消失前将 gizmo 在屏幕上保持指定的时间。 |
fadeOut | 当持续一定时间后,使消失过程淡出。 |
组合在一起
那么,您如何几乎在客户端管道的任何地方提交 gizmo 进行渲染?这一切都从 Gizmos#withCollector 和 SimpleGizmoCollector 开始。
SimpleGizmoCollector 基本上只是一个保存收集到的要渲染的 gizmo 的列表。在渲染过程中,调用 SimpleGizmoCollector#drainGizmos,将 gizmo 复制到一个单独的列表中,供渲染器通过熟悉的帧通道和缓冲区源在 Gizmo#emit 之前使用。然后,drainGizmos 根据 GizmoProperties#persistForMillis 清除内部列表,如果未指定则立即清除,以供下一帧使用。
为了实际收集这些元素,有一个相当复杂的过程。Minecraft、LevelRenderer 和 IntegratedServer 都有自己的 SimpleGizmoCollector。这是通过使用 Gizmo#withCollector 设置收集器来完成的,它返回一个 Gizmos$TemporaryCollection。该集合是 AutoCloseable 的,当关闭时,会释放本地线程上持有的收集器。因此,收集器被包装在 try-with-resources 中,以便在这些期间促进提交。然后,在调试通道期间,每Tick的 gizmo 与每帧的 gizmo 合并,并通过 addTemporaryGizmos 绘制到屏幕上,实际上是在 LevelRenderer#renderLevel 的最后一刻。在单机世界中,IntegratedServer 的 gizmo 存储在一个易失性字段中,允许从客户端线程访问它。
net.minecraft.client.MinecraftcollectPerTickGizmos- 返回所有要发出的 gizmo 的集合。getPerTickGizmos- 获取要绘制到屏幕的 gizmo。
net.minecraft.client.rendererLevelRenderer#collectPerFrameGizmos- 返回所有要发出的 gizmo 的集合。OrderedSubmitNodeCollector#submitHitbox已移除ShapeRendererrenderShape现在接受一个线宽floatrenderLineBox->Gizmos#cuboid,不是一对一addChainedFilledBoxVertices->Gizmos#cuboid,不是一对一renderFace->Gizmos#rect,不是一对一renderVector->Gizmos#line,不是一对一
SubmitNodeCollection#getHitboxSubmits已移除SubmitNodeStorage$HitboxSubmit记录已移除
net.minecraft.client.renderer.debugDebugRendererrender->emitGizmos,不再接受PoseStack、BufferSource或boolean,现在接受部分刻floatrenderFilledUnitCube->Gizmos#cuboid,不是一对一renderFilledBox->Gizmos#cuboid,不是一对一renderTextOverBlock->Gizmos#billboardTextOverBlock,不是一对一renderTextOverMob->Gizmos#billboardTextOverMob,不是一对一renderFloatingText->Gizmos#billboardText,不是一对一renderVoxelShape->LevelRenderer#renderHitOutline,现在是私有的,不是一对一SimpleDebugRenderer$render->emitGizmos,不再接受PoseStack、BufferSource或boolean,现在接受部分刻float
GameTestBlockHighlightRendererrender->emitGizmos,不接受参数renderMarker不再接受PoseStack或缓冲区源$Marker#get*已移除
LightDebugRenderer现在接受两个标志,决定是否显示块光或天空光PathfindingRenderer#renderPath、renderPathLine不再接受PoseStack或缓冲区源
net.minecraft.client.renderer.entity.EntityRenderer#extractAdditionalHitboxes已移除net.minecraft.client.renderer.entity.stateEntityRenderState#hitboxesRenderState、serverHitboxesRenderState已移除HitboxesRenderState类已移除ServerHitboxesRenderState类已移除
net.minecraft.client.renderer.feature.HitboxFeatureRenderer->EntityHitboxDebugRenderer,不是一对一net.minecraft.client.renderer.gizmos.DrawableGizmoPrimitives- 用于图元形状或 gizmo 的存储和渲染器。net.minecraft.client.renderer.textureAbstractTexturesampler、getSampler- 返回纹理使用的GpuSampler。setClamp->GpuSampler#getAddressMode*,不是一对一setFilter->GpuSampler#get*Filter,不是一对一
ReloadableTexture不再接受地址模式和过滤boolean
net.minecraft.client.server.IntegratedServer#getPerTickGizmos- 获取当前Tick要绘制到屏幕的 gizmo。net.minecraft.gizmosArrowGizmo- 一个绘制箭头的 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和数据包处理。
权限大修
权限级别整数已被扩展为一个既简单又复杂的新系统。有三个主要部分:Permission、PermissionSet 和 PermissionCheck。
权限
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 对象,它接受 PermissionSet 并 check 用户是否具有继续执行所需的数据。原版提供了两种类型的检查:$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.commandsCommandsLEVEL_*现在是PermissionCheck而不是inthasPermission现在接受PermissionCheck而不是int,并返回PermissionProviderCheck而不是PermissionCheckcreateCompilationContext- 使用给定的权限创建源堆栈。
CommandSourceStack不再实现PermissionSource- 构造函数现在接受
PermissionSet而不是int protected构造函数现在是privatewithPermission现在接受PermissionSet而不是intwithMaximumPermission现在接受PermissionSet而不是int
- 构造函数现在接受
ExecutionCommandSource现在扩展PermissionSetSupplier而不是PermissionSourcePermissionSource接口已移除SharedSuggestionProvider现在扩展PermissionSetSupplier
net.minecraft.commands.arguments.selector.EntitySelectorParser#allowSelectors现在有一个接受PermissionSetSupplier的重载net.minecraft.core.registriesBuiltInRegistries#PERMISSION_TYPE、Registries#PERMISSION_TYPE- 一个定义某些数据需求的对象。BuiltInRegistries#PERMISSION_CHECK_TYPE、Registries#PERMISSION_CHECK_TYPE- 一个谓词,检查集合是否具有所需的数据。
net.minecraft.serverMinecraftServeroperatorUserPermissionLevel->operatorUserPermissions,不是一对一getFunctionCompilationLevel->getFunctionCompilationPermissions,不是一对一getProfilePermissions现在返回LevelBasedPermissionSet
ReloadableServerResources#loadResources现在接受PermissionSet而不是intServerFunctionLibrary现在接受PermissionSet而不是intWorldLoader$InitConfig现在接受PermissionSet而不是int
net.minecraft.server.commands.PermissionCheck->.server.permissions.PermissionCheck,不是一对一net.minecraft.server.dedicated.DedicatedServerPropertiesopPermissionLevel->opPermissions,不是一对一functionPermissionLevel->functionPermissions,不是一对一deserializePermissions、serializePermission- 读取和写入选定的级别权限集。
net.minecraft.server.jsonrpc.internalapiMinecraftOperatorListService#op现在接受一个可选的PermissionLevel而不是intMinecraftServerSettingsServicegetOperatorUserPermissionLevel->getOperatorUserPermissions,不是一对一setOperatorUserPermissionLevel->setOperatorUserPermissions,不是一对一
net.minecraft.server.jsonrpc.methodsOperatorService$OperatorDto#permissionLevel现在接受一个可选的PermissionLevel而不是intServerSettingsServiceoperatorUserPermissionLevel现在返回PermissionLevel而不是intsetOperatorUserPermissionLevel现在接受并返回PermissionLevel而不是int
net.minecraft.server.permissionsLevelBasedPermissionSet- 一组权限,检查用户是否具有相等或更高的命令权限级别。Permission- 与用户权限相关的数据,例如命令级别。PermissionCheckTypes- 原版提供的权限检查类型。PermissionLevel- 定义权限的级别序列。PermissionProviderCheck- 一个谓词,检查供应商的权限集与检查的匹配。Permissions- 原版提供的权限。PermissionSet- 一组用户拥有的权限,但主要定义一个方法来确定用户是否具有所需的权限。PermissionSetSupplier- 一个提供PermissionSet的对象。PermissionSetUnion- 多个权限集的联合。PermissionTypes- 原版提供的权限类型。
net.minecraft.server.playersPlayersList#op现在接受一个可选的LevelBasedPermissionSet而不是intServerOpListEntry现在接受LevelBasedPermissionSet而不是intgetLevel->permissions,不是一对一
net.minecraft.world.entity.player.Player#getPermissionLevel、hasPermissions->permissions,不是一对一net.minecraft.world.entity.projectile.ProjectileUtilsgetHitEntitiesAlong- 获取沿提供路径击中的实体。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 定义了用此物品击中实体时应用于实体的伤害类型。它接受伤害类型的 ResourceKey 或 DamageType 对象本身。
// 对于某个物品注册
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.componentsDataComponentsUSE_EFFECTS- 使用物品时应用于实体的效果。MINIMUM_ATTACK_CHARGE- 使用物品攻击的最短时间。DAMAGE_TYPE- 物品造成的DamageTypePIERCING_WEAPON- 一种具有某些碰撞箱范围并向实体冲刺的武器。KINETIC_WEAPON- 一种需要一定前进动量的具有碰撞箱范围的武器。SWING_ANIMATION- 挥动物品时应用的动画。ATTACK_RANGE- 使用物品时设置自定义攻击范围,覆盖正常的实体交互范围。
net.minecraft.core.component.DataComponentType#ignoreSwapAnimation、$Builder#ignoreSwapAnimation- 当为 true 时,交换动画不会影响数据组件的“使用”。net.minecraft.core.component.predicatesAnyValue- 一个谓词,检查获取器上是否存在该组件。DataComponentPredicate$Type现在是一个接口- 其原始实现已被
$TypeBase取代
- 其原始实现已被
$AnyValueType- 一个使用AnyValue谓词的类型。$ConcreteType- 一个定义特定谓词的类型。
net.minecraft.network.protocol.game.ServerboundInteractPacket#isWithinRange- 玩家的交互是否在有效范围内以执行。net.minecraft.world.entityLivingEntitySWING_DURATION->SwingAnimation#duration,不是一对一stabbedEntities- 最近被动能武器攻击的实体数量。entityAttackRange- 此实体可以攻击的范围。getActiveItem- 当前使用的物品,或主手物品。
MobchargeSpeedModifier- 冲刺时应用于移动速度的修改器。canFireProjectileWeapon->canUseNonMeleeWeapon,现在接受ItemStack而不是ProjectileWeaponItemgetAttackBoundingBox现在接受一个水平膨胀偏移
net.minecraft.world.entity.ai.behaviorChargeAttack- 处理生物执行的冲刺攻击。SpearApproach- 当持有动能武器时接近敌人。SpearAttack- 使用动能武器攻击敌人。SpearRetreat- 使用动能武器后从攻击目标逃跑。
net.minecraft.world.entity.ai.goal.SpearUseGoal- 处理生物使用矛。net.minecraft.world.entity.ai.memory.MemoryModuleTypeSPEAR_FLEEING_TIME- 使用动能武器后实体已逃跑的刻数。SPEAR_FLEEING_POSITION- 使用动能武器后实体逃跑到的位置。SPEAR_CHARGE_POSITION- 使用动能武器时实体冲刺到的位置。SPEAR_ENGAGE_TIME- 使用动能武器时此实体与敌人交战的时间。SPEAR_STATUS- 使用动能武器时实体的状态。
net.minecraft.world.entity.player.PlayerhasEnoughFoodToDoExhaustiveManoeuvres- 返回玩家是否可以进行消耗体力的机动。canInteractWithEntity->isWithinEntityInteractionRangeisWithinAttackRange- 被瞄准的边界框是否在玩家的范围内。canInteractWithBlock->isWithinBlockInteractionRangeCREATIVE_ENTITY_INTERACTION_RANGE_MODIFIER_VALUE- 一个修饰符,将交互的最大范围增加给定的数量。
net.minecraft.world.itemItem#getDamageSource->getItemDamageSource,现已弃用ItemStackgetSwingAnimation- 返回物品的挥动动画。getDamageSource- 返回物品被击中时提供的伤害来源。causeUseVibration- 如果使用中的物品可以引起振动,则发送游戏事件。
SwingAnimationType- 挥动物品时播放的动画类型。
net.minecraft.world.item.componentAttackRange- 此物品的碰撞箱范围。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 定义的层获得:
- 从注册的属性中读取默认值(通过
EnvironmentAttribute#defaultValue)。 - 应用来自维度的修改器,如果该属性不存在则不执行任何操作。
- 应用来自生物群系的修改器,如果不存在则不执行任何操作。
- 应用
DimensionType中定义的所有活动时间线的修改器,如果不存在则不执行任何操作。时间线顺序不保证。 - 如果维度可以有天气(天空光照、无天花板、且不是末地),则应用
WeatherAttributes的修改器。 - 如果在客户端(即
ClientLevel),则应用天空闪光修改器。 - 将最终值清理到
EnvironmentAttribute定义的范围内。
这是高度简化的,并引入了许多新概念,因此让我们通过创建我们自己的环境属性和时间线来进一步分解。
自定义环境属性
环境属性通过 $Builder 创建,使用 EnvironmentAttribute#builder,接受其表示的类型值(例如,浮点数、整数、对象)。构建器只需要设置一个值:defaultValue。如果维度或生物群系未覆盖该属性,则使用此值。如果属性值应具有一组有效的状态,则可以通过 valueRange 设置 AttributeRange。AttributeRange 基本上是一个一元运算符,通过 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。这不仅定义了如何序列化对象值,还包含可以应用于值的修改以及如何在空间和帧之间进行插值。实际上,包括 syncable 和 spatiallyInterpolated 在内的所有构建器设置都依赖于属性类型来确定执行该操作意味着什么。如果没有它,甚至无法从维度或生物群系 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$OperationId 到 AttributeModifier 的映射,确定可以对默认值执行哪些操作。如果映射不包含任何操作,则默认值不能更改。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: 村民执行什么Activityminecraft:early_game: 在最初几天阻止掠夺者巡逻队生成
关联的标签如下:
minecraft:universalminecraft:villager_schedule
minecraft:in_overworld- 主世界维度#minecraft:universalminecraft:dayminecraft:moonminecraft:early_game
minecraft:in_nether- 下界维度#minecraft:universal
minecraft:in_end- 末地维度#minecraft:universal
关键帧
每个 Timeline 由关键帧组成,负责确定在给定刻时修改器的参数应该是什么。然后,这些关键帧被编译成一个称为 KeyframeTrack 的列表,在构造属性层时烘焙成一个 KeyframeTrackSampler。每两个相邻的关键帧(包括第一个和最后一个)被认为是一个 KeyframeTrackSampler$Segment。这就是用于在给定刻采样属性的内容。
假设我们有以下(关键帧,值)段 (100, 0) -> (200, 1),并且我们当前在 150 刻。我们如何选择使用什么参数?这通过两个操作执行。首先,我们计算步长:介于 0 和 1 之间的值,决定与值进行多少插值。步长首先线性计算:(current_tick - start_segment_tick) / (end_segment_tick - start_segment_tick)。然后,将步长传递给所需的 EasingType,这是一个接受 0-1 值并返回 0-1 值的函数,例如 in_out_bounce 或 out_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.clientCamera#attributeProbe- 获取客户端环境属性探测器的值和插值。MinecraftgetSituationalMusic现在返回Music而不是MusicInfogetMusicVolume- 获取背景音乐的音量,如果打开的屏幕有背景音乐则获取正常音量。
net.minecraft.client.multiplayer.ClientLeveleffects已移除getSkyDarken->EnvironmentAttributes#SKY_LIGHT_COLOR、SKY_LIGHT_FACTOR;不是一对一getSkyColor->EnvironmentAttributes#SKY_COLOR,不是一对一getCloudColor->EnvironmentAttributes#CLOUD_COLOR,不是一对一getStarBrightness->EnvironmentAttributes#STAR_BRIGHTNESS,不是一对一getSkyFlashTime现在是私有的
net.minecraft.client.rendererDimensionSpecialEffects类已移除,完全被EnvironmentAttribute取代SkyRendererrenderSkyDisc现在接受一个 ARGBint而不是三个 RGBfloatrenderSunMoonAndStars现在接受两个额外的float用于月亮和星星的旋转
net.minecraft.client.renderer.state.SkyRenderStateskyType->skybox,不是一对一isSunriseOrSunset、timeOfDay已移除moonAngle、starAngle- 月亮和星星的角度。
net.minecraft.client.resources.sounds.BiomeAmbientSoundsHandler不再接受BiomeManagernet.minecraft.client.soundsMusicInfo->Minecraft#getSituationalMusic、getMusicVolume;不是一对一MusicManager#startPlaying现在接受Music而不是MusicInfo
net.minecraft.core.registriesBuiltInRegistries、Registries#ENVIRONMENT_ATTRIBUTE- 环境属性的注册表。BuiltInRegistries、Registries#ATTRIBUTE_TYPE- 属性类型的注册表。BuiltInRegistires、Registries#SCHEDULE已移除Registries#TIMELINE- 时间线的注册表键。
net.minecraft.data.tags.TimelineTagsProvider- 时间线的标签提供者。net.minecraft.server.level.ServerLevel#getMoonBrightness- 返回月亮的亮度。net.minecraft.sounds.Music#event->soundnet.minecraft.tags.TimelineTags- 时间线的标签。net.minecraft.utilBinaryAnimator$EasingFunction->EasingTypeCubicSampler->GaussianSampler、SpatialAttributeInterpolator;不是一对一KeyframeTrack- 一个关键帧轨道以及它们之间执行的缓动。KeyframeTrackSampler- 一个基于周期重播的关键帧轨道,使用提供的函数在值之间进行插值。
net.minecraft.world.attributeAmbientSounds- 在环境中环境播放的声音。AttributeRange- 一个接口,用于验证输入并将相应值清理到适当的边界。AttributeType- 属性可以执行的操作和修改的类型定义。AttributeTypes- 所有原版属性类型的注册表。BackgroundMusic- 在环境中播放的背景音乐。BedRule- 环境中床的功能规则。EnvironmentAttribute- 环境中某个属性的定义。EnvironmentAttributeLayer- 一个修改值的层。EnvironmentAttributeMap- 属性定义到其参数和修改器的映射。EnvironmentAttributeProbe- 用于获取和插值值的属性处理程序。仅由相机使用。EnvironmentAttributeReader- 一个可以通过维度或位置查找环境属性的读取器。EnvironmentAttributes- 所有原版环境属性的注册表。EnvironmentAttributeSystem- 一个获取和空间插值环境属性的读取器实现。LerpFunction- 一个函数式接口,接受 0-1 之间的某个值以及起始和结束值以在之间进行插值。WeatherAttributes- 用于应用天气层的属性映射。
net.minecraft.world.attribute.holderAttributeModifier- 一个修改器,接受属性值以及某个参数(通常是相同类型的值)以产生修改后的值。BooleanModifier- 带有布尔参数的布尔值修改器。ColorModifier- 带有某个参数(通常是整数)的 ARGB 整数修改器。FloatModifier- 带有某个参数(通常是浮点数或带有 alpha 插值器的浮点数)的浮点数修改器。FloatWithAlpha- 一个包含某个值和通常用于混合的 alpha 的记录。
net.minecraft.world.entity.ai.BraingetSchedule已移除setSchedule现在接受EnvrionmentAttribute<Activity>而不是ScheduleupdateActivityFromSchedule现在接受EnvironmentAttributeSystem和位置而不是白天时间
net.minecraft.world.entity.animal.bee.Bee#isNightOrRaining被EnvironmentAttributes#BEES_STAY_IN_HIVE取代net.minecraft.world.entity.player.Player$BedSleepingProblem现在是一个记录NOT_POSSIBLE_HERE->BedRule#EXPLODESNOT_POSSIBLE_NOW->BedRule#CAN_SLEEP_WHEN_DARK
net.minecraft.world.entity.scheduleKeyframe->.minecraft.util.Keyframe,不是一对一Schedule已移除,其逻辑被Timeline、Timelines取代ScheduleBuilder已移除,其逻辑被Timeline$Builder取代Timeline->.world.timeline.Timeline,不是一对一
net.minecraft.world.entity.variant.SpawnContext现在接受EnvironmentAttributeReadernet.minecraft.world.levelLevelisMoonVisible被EnvironmentAttributes#MOON_ANGLE取代getSunAngle被EnvironmentAttributes#SUN_ANGLE取代canHaveWeather现在是public
LevelAccessor现在实现LevelReader而不是LevelTimeAccessLevelReader#environmentAttributes- 返回管理器,用于获取维度及其关联生物群系内的环境属性。LevelTimeAccess接口已移除MoonPhaseCODEC- 月相的编解码器。PHASE_LENGTH- 月相存在的刻数。startTick- 特定相位的开始刻。
net.minecraft.world.level.biomeAmbientAdditionsSettings->.world.attribute.AmbientAdditionsSettingsAmbientMoodSettings->.world.attribute.AmbientMoodSettingsAmbientParticleSettings->.world.attribute.AmbientParticleBiome现在接受EnvironmentAttributeMapgetSkyColor->EnvironmentAttributes#SKY_COLORgetFogColor->EnvironmentAttributes#FOG_COLORgetAttributes- 获取此生物群系的属性。getWaterFogColor->EnvironmentAttributes#WATER_FOG_COLORgetAmbientParticle->EnvironmentAttributes#AMBIENT_PARTICLESgetAmbientLoop->AmbientSounds#loop环境属性getAmbientMood->AmbientSounds#mood环境属性getAmbientAdditions->AmbientSounds#additions环境属性getBackgroundMusic->EnvironmentAttributes#BACKGROUND_MUSICgetBackgroundMusicVolume->EnvironmentAttributes#MUSIC_VOLUME$BuilderputAttributes- 从另一个映射放入所有属性。setAttribute- 设置一个环境属性。modifyAttribute- 修改生物群系的属性源。
BiomeSpecialEffects现在是一个记录getFogColor->EnvironmentAttributes#FOG_COLORgetWaterFogColor->EnvironmentAttributes#WATER_FOG_COLORgetSkyColor->EnvironmentAttributes#SKY_COLORgetAmbientParticleSettings->EnvironmentAttributes#AMBIENT_PARTICLESgetAmbientLoopSoundEvent->AmbientSounds#loop环境属性getAmbientMoodSettings->AmbientSounds#mood环境属性getAmbientAdditionsSettings->AmbientSounds#additions环境属性getBackgroundMusic->EnvironmentAttributes#BACKGROUND_MUSICgetBackgroundMusicVolume->EnvironmentAttributes#MUSIC_VOLUME
net.minecraft.world.level.blockBedBlock#canSetSpawn->BedRule#canSetSpawn环境属性CreakingHeartBlock#isNaturalNight被EnvironmentAttributes#CREAKING_ACTIVE取代RespawnAnchorBlock#canSetSpawn现在接受ServerLevel和BlockPos
net.minecraft.world.level.dimensionBuiltinDimensionTypes#*_EFFECTS已移除DimensionDefaults#OVERWORLD_CLOUD_HEIGHT现在是一个floatDimensionTypefixedTime->hasFixedTime,现在是boolean而不是OptionalLongnatural、effectsLocation已移除skybox- 在维度内显示的天空盒。cardinalLightType- 贯穿维度的光线类型。timelines- 一组修改此维度环境属性的时间线。ultraWarm->EnvironmentAttributes#WATER_EVAPORATES、FAST_LAVA、DEFAULT_DRIPSTONE_PARTICLEbedWorks->EnvironmentAttributes#BED_RULErespawnAnchorWorks->EnvironmentAttributes#RESPAWN_ANCHOR_WORKScloudHeight->EnvironmentAttributes#CLOUD_HEIGHTattribute- 获取此维度的属性。piglinSafe、$MonsterSettings#piglinSafe->EnvironmentAttributes#PIGLINS_ZOMBIFYhasRaids、$MonsterSettings#hasRaids->EnvironmentAttributes#CAN_START_RAIDtimeOfDay已移除moonPhase被EnvironmentAttributes#MOON_PHASE取代hasEndFlashes- 返回天空盒是否是末地。$CardinalLightType- 贯穿维度的光线。$Skybox- 维度的天空盒。
net.minecraft.world.level.material.FogType#DIMENSION_OR_BOSS已移除net.minecraft.world.timelineAttributeTrack- 一个轨道,应用属性修改器,其参数从给定的关键帧轨道采样。AttributeTrackSampler- 一个烘焙的属性轨道。Timeline- 一个属性到轨道的映射,基于时间(以刻为单位)模周期应用。Timelines- 所有原版时间线。
游戏规则洗牌
游戏规则系统已在一定程度上被改造,允许将其键存储为适当的注册表对象,同时仍将其值限制为整数或布尔值。大多数类基本上只是其他类的组合。
现有游戏规则
现有的游戏规则仍然在 GameRules 类中,只是移到了不同的位置。它们的字段已被重命名,并似乎遵循一些基本规则:
- 规则不再有
RULE_前缀 - 规则现在使用下划线分隔单词
DO前缀已从规则名称中移除(例如,RULE_DOENTITYDROPS->ENTITY_DROPS)SPAWNING后缀已替换为SPAWN_前缀(例如,RULE_DOMOBSPAWNING->SPAWN_MOBS)DISABLE前缀已移除,意味着它们的值被反转(例如,RULE_DISABLERAIDS->RAIDS)
虽然有一些边缘情况,但在之前的游戏规则名称中搜索特定单词很可能会引导您找到新名称(例如,在 RULE_ANNOUNCEADVANCEMENTS 中搜索 ADVANCEMENT 会找到 SHOW_ADVANCEMENT_MESSAGES)。
要实际从游戏规则中获取值,您将使用 GameRules#get 而不是之前的 getBoolean 和 getInteger。类型从注册的 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$Type 和 GameRules$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.worldselectionEditGameRulesScreen$BooleanRuleEntry现在接受GameRule<Boolean>而不是GameRules$BooleanValue$EntryFactory不再限制其泛型$IntegerRuleEntry现在接受GameRule<Integer>而不是GameRules$IntegerValue
InitialWorldCreationOptions#disabledGameRules现在是一个GameRuleMap
net.minecraft.core.registries.BuiltInRegistries#GAME_RULE、Registries#GAME_RULE- 游戏规则注册表。net.minecraft.gametest.framework.TestEnvironmentDefinition$SetGameRules现在接受GameRulesMap而不是$Entryentry、$Entry已移除
net.minecraft.server.MinecraftServer#onGameRuleChanged现在接受GameRule和值,而不是字符串键和$Value包装器net.minecraft.server.jsonrpc.api.SchemaRULE_TYPE_SCHEMA现在是GameRuleType而不是GameRulesService$RuleTypeTYPED_GAME_RULE_SCHEMA现在是GameRulesService$GameRuleUpdate而不是GameRulesService$TypedRuleUNTYPED_GAME_RULE_SCHEMA现在是GameRulesService$GameRuleUpdate而不是GameRulesService$UntypedRule
net.minecraft.server.jsonrpc.internalapiGameRules接口已移除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处理getBoolean、getInteger->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.inputInputWithModifiers$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.guiActiveTextCollector- 一个用于渲染具有某些参数和对齐方式的文本的辅助工具。GuiGraphics现在接受鼠标 XYtextRenderer*- 用于构造在适当位置提交文本的辅助工具的方法。$HoveredTextEffects- 一个枚举,定义在使用文本收集器时应用的文本效果。
net.minecraft.client.gui.componentsAbstractButton现在扩展AbstractWidget$WithInactiveMessage而不是AbstractWidgetrenderWidget现在是 final- 请改用
renderContents来提交元素 - 应在
renderContents中调用renderDefaultSprite以 blit 默认精灵
- 请改用
renderString->renderDefaultLabel,不是一对一
AbstractSliderButton现在扩展AbstractWidget$WithInactiveMessage而不是AbstractWidgetAbstractStringWidgetvisitLines- 处理将文本元素提交到屏幕。setColor、getColor已移除- 请改用
visitLines中的ActiveTextCollector
- 请改用
setComponentClickHandler- 设置当点击具有提供样式的组件时的处理程序。
AbstractWidgetrenderScrollingString->renderScrollingStringOverContents,不是一对一getAlpha- 获取小部件的 alpha 值。$WithInactiveMessage- 一个小部件,可以在不活动时更改显示的消息。
Button现在是抽象的$Plain复制了以前的行为
ChatComponentMESSAGE_BOTTOM_TO_MESSAGE_TOP- 聊天组件的高度。render现在接受Font和一个boolean,表示是否在插入时更改光标captureClickableText- 捕获要提交的可点击文本。handleChatQueueClicked被QUEUE_EXPAND_ID取代,不是一对一getClickedComponentStyleAt->$ChatGraphicsAccess#handleMessage,不是一对一getMessageTagAt->$ChatGraphicsAccess#handleTag、handleTagIcon;不是一对一getWidth、getHeight、getScale现在是私有的$AlphaCalculator- 计算给定聊天行的 alpha 值。$ChatGraphicsAccess- 一个用于处理聊天输入提交的接口。$LineConsumer不再接受前三个int
FittingMultilineTextWidget#setColor已移除- 请改用
visitLines中的ActiveTextCollector
- 请改用
MultiLineLabelrender、getStyle->visitLines,不是一对一$Align->TextAlignment
MultiLineTextWidget#setColor、configureStyleHandling已移除- 请改用
visitLines中的ActiveTextCollector
- 请改用
SplashRenderer现在接受Component而不是StringSpriteIconButton#renderSprite- 提交精灵图标。StringWidget#setColor已移除- 请改用
visitLines中的ActiveTextCollector
- 请改用
TabButton现在扩展AbstractWidget$WithInactiveMessage而不是AbstractWidgetrenderString->renderLabel,现在是私有的,不是一对一
net.minecraft.client.gui.screens.inventory.BookViewScreen#getClickedComponentStyleAt->visitText,现在是私有的,不是一对一
共享文本区域调试器
添加了一个新的调试器,用于绘制每个字形的边界框,包括空字形。颜色在每个字形之间略有偏移以便于区分,并且根据是否存在点击或悬停事件的某种组合而完全改变。
net.minecraft.SharedConstants#DEBUG_ACTIVE_TEXT_AREAS- 用于调试器绘制每个字形的边界和效果的标志。net.minecraft.client.gui.FontprepareText现在有一个重载,表示是否在空区域渲染某些内容$GlyphVisitoracceptGlyph现在接受TextRenderable$Styled而不是TextRenderableacceptEmptyArea- 接受一个空区域以绘制到屏幕。
$PreparedTextBuilder现在接受是否包括空区域以进行渲染
net.minecraft.client.gui.fontActiveArea- 定义要绘制区域的边界和样式。EmptyArea- 一个内部没有任何内容的区域。PlainTextRenderable现在实现TextRenderable$Styled而不是TextRenderablewidth、height、ascent- 对象的边界。
TextRenderable$Styled- 一个为其边界定义某个活动区域的文本可渲染对象。
net.minecraft.client.gui.font.glyphs.BakedGlyph#createGlyph现在返回TextRenderable$Styled
JSpecify 注解
Mojang 已从使用他们自己的注解混合,转向在需要时使用 JSpecify 提供的注解。因此,不再默认所有字段、方法和参数都被标记为非空,而是由 NullMarked 取代,它认为类型用法是非空的,除非显式注解为 Nullable,除了一些特殊情况。
com.mojang.blaze3d.FieldsAreNonnullByDefault、MethodsReturnNonnullByDefault已移除com.mojang.math.FieldsAreNonnullByDefault、MethodsReturnNonnullByDefault已移除net.minecraft.FieldsAreNonnullByDefault、MethodsReturnNonnullByDefault已移除
槽位来源
槽位来源是对之前在潜影盒中的内容掉落系统的扩展,允许任何战利品表从某些容器槽位中提取其条目。这可以在任何启用 LootContext 的位置使用,尽管目前它仅作为战利品池条目实现。
在原版中,槽位来源的工作方式是让某个 LootContextArg(指向某个战利品上下文参数值)返回一个实现 SlotProvider 的对象。目前,这指的是任何 Container 或 Entity 实现。然后,SlotProvider 被 SlotSource#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而不是Entitynet.minecraft.core.registries.BuiltInRegistries#SLOT_SOURCE_TYPE、Registries#SLOT_SOURCE_TYPE- 槽位来源类型注册表。net.minecraft.world.Container现在扩展SlotProvidergetSlot- 获取单个物品的访问。
net.minecraft.world.entityEntity现在实现SlotProviderSlotAccessNULL已移除forContainer->forListElement,不是一对一
SlotProvider- 一个通过槽位提供对其内部存储的某些访问的对象。
net.minecraft.world.item.slotCompositeSlotSource- 多个槽位来源的组合。ContentsSlotSource- 获取槽位内容。EmptySlotSource- 一个空的槽位来源。FilteredSlotSource- 根据物品谓词过滤提供的槽位来源。GroupSlotSource- 将多个槽位来源组合成一个连接的集合。LimitSlotSource- 将提供的槽位来源限制为最大大小。RangeSlotSource- 获取所需的槽位范围。SlotCollection- 一个槽位的集合,用于获取物品副本。SlotSource- 给定战利品上下文,返回一个要提供的槽位集合。SlotSources- 原版提供的槽位来源。TransformedSlotSource- 转换提供的槽位来源。
net.minecraft.world.level.storage.loot.ContainerComponentManipulator#getSlots- 获取堆栈上数据组件的槽位。net.minecraft.world.level.storage.loot.entriesLootPoolEntries#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.nautilusZombieNautilusVariant- 僵尸鹦鹉螺的变体。ZombieNautilusVariants- 所有原版僵尸鹦鹉螺变体。
OptionEnum 移除
OptionEnum 已被移除,转而使用带有期望值和编解码器的 OptionInstance$Enum 构造函数。因此,大多数 byId 方法已被一些编解码器取代,并且可翻译条目现在存储为 Component 而不是翻译键字符串。
net.minecraft.clientAttackIndicatorStatus不再实现OptionEnumbyId->LEGACY_CODEC,不是一对一getKey->caption,不是一对一
CloudStatus不再实现OptionEnumgetKey->caption,不是一对一
InactivityFpsLimit不再实现OptionEnumgetKey->caption,不是一对一
OptionInstance#forOptionEnum已移除PrioritizeChunkUpdate不再实现OptionEnumgetKey->caption,不是一对一byId->LEGACY_CODEC,不是一对一
net.minecraft.client.sounds.MusicManager$MusicFrequency不再实现OptionEnumgetKey->caption,不是一对一
net.minecraft.server.level.ParticleStatus不再实现OptionEnumgetKey->caption,不是一对一byId->LEGACY_CODEC,不是一对一
net.minecraft.util.OptionEnum已移除net.minecraft.world.entity.HumanoidArm不再实现OptionEnumBY_ID现在是私有的getKey->caption,不是一对一
net.minecraft.world.entity.player.ChatVisbility不再实现OptionEnumbyId->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:biomeplays_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:blockcan_glide_through
minecraft:entity_typeburn_in_daylightcan_float_while_riddencan_wear_nautilus_armornautilus_hostiles
minecraft:itemcamel_husk_foodzombie_horse_foodnautilus_bucket_foodnautilus_foodnautilus_taming_itemsspearsenchantable/lungeenchantable/sword->enchantable/melee_weapon、enchantable/sweeping
minecraft:timelineuniversalin_overworldin_netherin_end
新增列表
com.mojang.blaze3d.GraphicsWorkarounds#isAmd- GPU 供应商是否为 AMD。com.mojang.blaze3d.openglGlConst#GL_POINTS- 定义点图元作为要渲染的类型。GlTimerQuery- 查询对象(通常是经过的时间)的 OpenGL 实现。
com.mojang.blaze3d.platform.InputConstants#MOUSE_BUTTON_*- 鼠标点击的输入,用数字表示,因为它们可能有不同的预期用途。com.mojang.blaze3d.systemsCommandEncoder#timerQueryBegin、timerQueryEnd- 用于跟踪经过时间的处理程序。GpuQuery- 对任意对象的查询,例如经过的时间。
com.mojang.blaze3d.vertexDefaultVertexFormatPOSITION_COLOR_LINE_WIDTH- 一个指定位置、颜色和线宽的顶点格式。POSITION_COLOR_NORMAL_LINE_WIDTH- 一个指定位置、颜色、法线和线宽的顶点格式。
VertexFormat$Mode#POINTS- 一个绘制点的顶点模式。VertexFormatElement#LINE_WIDTH- 一个接受一个表示宽度的浮点数的顶点元素。
com.mojang.mathOctahedralGroupBLOCK_ROT_*- 表示方块旋转的常量。permutation- 返回对称群。
Quadrant#fromXYZAngles- 获取表示三个象限旋转的八面体群。SymmetricGroup3#inverse- 返回逆群。
net.minecraftSharedConstantsMAX_CLOUD_DISTANCE- 玩家可以渲染的最大云范围。DEFAULT_RANDOM_TICK_SPEED- 默认随机刻速度。
Util#localizedDateFormatter- 返回给定样式的本地化DateTimeFormatter。
net.minecraft.advancements.criterionDataComponentMatchers$Builder#any- 匹配组件的某些数据是否存在。SpearMobsTrigger- 一个触发器,检查玩家使用动能武器刺穿的实体数量。
net.minecraft.clientGuiMessagesplitLines- 将组件以所需宽度拆分为行。getTagIconLeft- 获取内容的宽度,外加四个像素的填充。
KeyMapping$Category#DEBUG- 调试键盘类别。MusicToastDisplayState- 一个枚举,表示音乐吐司应如何显示。NarratorStatus#LEGACY_CODEC- 用于反序列化枚举旁白状态的编解码器。OptionInstance$IntRangeBasenext- 获取下一个值。previous- 获取上一个值。
$SliderableEnum- 一个在枚举选项之间选择的滑块。$SliderableValueSetnext- 获取下一个值。previous- 获取上一个值。
OptionskeyToggleGui- 一个切换游戏内 GUI 的按键映射。keyToggleSpectatorShaderEffects- 一个切换与相机实体绑定的着色器效果的按键映射。keyDebug*、debugKeys- 调试渲染器的按键映射。weatherRadius- 区域中天气粒子渲染的半径。cutoutLeaves- 树叶是否应以切割或实体模式渲染。vignette- 是否应在屏幕上应用晕影。improvedTransparency- 是否使用透明度后处理器。chunkSectionFadeInTime- 区块首次渲染时淡入应花费的秒数。maxAnisotropyBit- 各向异性过滤级别的位值。maxAnisotropyValue- 各向异性过滤级别。
net.minecraft.client.animation.definitions.NautilusAnimation- 鹦鹉螺的动画定义。net.minecraft.client.data.models.ItemModelGeneratorsgenerateSpear- 生成矛物品模型。generateItemWithTintedBaseLayer- 生成一个基础层被染色的双层物品模型。
net.minecraft.client.data.models.model.ModelTemplates#SPEAR_IN_HAND- 手持矛模型的模板。net.minecraft.client.gui.componentsAbstractButton#setOverrideRenderHighlightedSprite- 覆盖是否使用聚焦启用/禁用精灵。Checkbox#adjustWidth- 使用消息、字体及其初始 X 位置设置小部件的宽度。CycleButton$Builder#withSprite- 设置根据当前按钮状态获取精灵的供应商。$DisplayState- 按钮应如何显示。$SpriteSupplier- 根据当前按钮状态获取精灵位置。
EditBox#setInvertHighlightedTextColor- 设置是否反转高亮文本颜色。FocusableTextWidgetgetPadding- 返回文本填充。updateWidth- 更新文本可以占用的宽度。updateHeight- 更新文本可以占用的高度。$Builder- 构建组件。
MultiLineTextWidget#getTextX、getTextY- 获取文本位置。OptionsListaddHeader- 添加一个标题条目。resetOption- 重置选项值。$AbstractEntry- 定义选择列表中的元素。$HeaderEntry- 一个表示部分标题的条目。$OptionInstanceWidget- 一个包含小部件和可选的选项实例的记录。
ResettableOptionWidget- 一个可以将其值重置为默认值的小部件。SelectableEntry- 一个用于检查鼠标是否在特定区域的实用程序。
net.minecraft.client.gui.layouts.HeaderAndFooterLayout#MAGIC_PADDING- 元素之间的常见填充。net.minecraft.client.gui.screens.advancementsAdvancementTab#canScrollHorizontally、canScrollVertically- 检查标签页数据是否可以在给定方向上滚动。AdvancementTabType#getWidth、getHeight- 获取标签页的宽度/高度。
net.minecraft.client.gui.screens.debug.DebugOptionsScreen#getOptionList- 返回调试屏幕的选项列表。net.minecraft.client.gui.screens.inventoryAbstractMountInventoryScreen- 一个表示坐骑库存的屏幕。EffectsInInventorySPACING- 效果之间的间距。SPRITE_SQUARE_SIZE- 效果图标的大小。
NautilusInventoryScreen- 鹦鹉螺库存的屏幕。
net.minecraft.client.gui.screens.optionsOptionsSubScreen#resetOption- 将选项值重置为默认值。VideoSettingsScreen#updateTransparencyButton- 将透明度按钮设置为当前选项值。
net.minecraft.client.gui.screens.packs.TransferableSelectionList$PackEntry#ICON_SIZE- 资源包图标的大小。net.minecraft.client.gui.screens.recipebook.RecipeBookTabButton#select、unselect- 处理标签页显示选择。net.minecraft.client.input.InputQuirks#EDIT_SHORTCUT_KEY_LEFT、EDIT_SHORTCUT_KEY_RIGHT->InputWithModifiers#hasControlDownWithQuirk,不是一对一net.minecraft.client.model.HumanoidModel$ArmPoseSPEAR- 矛的第三人称手臂姿势。animateUseItem- 给定实体状态、使用时间、手臂和堆栈,修改PoseStack。affectsOffhandPose- 手臂动画是否会影响副手姿势。
net.minecraft.client.model.animal.nautilusNautilusArmorModel- 鹦鹉螺的盔甲模型。NautilusModel- 鹦鹉螺的模型。NautilusSaddleModel- 鹦鹉螺的马鞍模型。
net.minecraft.client.model.effects.SpearAnimations- 使用矛时执行的动画。net.minecraft.client.model.geomModelLayers*NAUTILUS*- 鹦鹉螺的模型层。UNDEAD_HORSE*_ARMOR- 亡灵马的盔甲模型层。
PartNameINNER_MOUTH、LOWER_MOUTH- 嘴的部件名称。SHELL- 壳的部件名称。*_CORAL*- 僵尸鹦鹉螺上珊瑚的部件名称。
net.minecraft.client.model.geom.builders.UVPair#pack、unpack*- 处理将 UV 打包/解包为long。net.minecraft.client.model.monster.nautilus.ZombieNautilusCoralModel- 僵尸鹦鹉螺温暖变体的模型。net.minecraft.client.model.monster.skeleton.SkeletonModel#createSingleModelDualBodyLayer- 创建一个焦尸层定义。net.minecraft.client.multiplayerClientPacketListener#hasClientLoaded- 客户端是否已加载。MultiPlayerGameMode#piercingAttack- 发起冲刺攻击。
net.minecraft.client.player.LocalPlayer#raycastHitResult- 获取给定部分刻下相机实体的命中结果。net.minecraft.client.rendererDynamicUniformsCHUNK_SECTION_UBO_SIZE- 区块部分的统一缓冲区对象大小。writeChunkSections- 将可变参数的区块部分写入统一存储。$ChunkSectionInfo- 区块部分的动态统一变量。
GameRendererupdateCamera- 调用相机的设置函数。getPanoramicScreenshotParameters- 获取全景模式的截图参数。
PanoramicScreenshotParameters- 全景模式的截图参数。Sheets#CELESTIAL_SHEET- 天体纹理的图集。
net.minecraft.client.renderer.blockentity.BlockEntityWithBoundingBoxRenderer#STRUCTURE_VOIDS_COLOR- 结构的虚空颜色。net.minecraft.client.renderer.chunk.SectionRenderDispatcher$RenderSectiongetVisibility- 返回区块当前的 alpha 值。setFadeDuration- 设置区块淡入所需的时间。setWasPreviouslyEmpty、wasPreviouslyEmpty- 处理该部分之前是否不存在。
net.minecraft.client.renderer.entityCamelHuskRenderer- 骆驼干尸的实体渲染器。CamelRenderer#createCamelSaddleLayer- 创建骆驼的马鞍层。NautilusRenderer- 鹦鹉螺的实体渲染器。ParchedRenderer- 焦尸的实体渲染器。ZombieNautilusRenderer- 僵尸鹦鹉螺的实体渲染器。
net.minecraft.client.renderer.entity.stateArmedEntityRenderStateswingAnimationType- 挥动手臂时播放的动画。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.modelBlockModelRotation#IDENTITY- 恒等旋转。EquipmentClientInfo#NAUTILUS_*- 鹦鹉螺的层。
net.minecraft.core.Vec3imultiply- 将每个分量乘以提供的标量。toMutable- 返回一个可变的Vector3i。
net.minecraft.data.AtlasIds#CELESTIAL_SHEET- 天体纹理的图集。net.minecraft.data.recipes.RecipeProvider#waxedChiseled- 打蜡的雕纹方块的配方。net.minecraft.gametest.framework.GameTestHelper#getAbsoluteDirection- 从测试相对方向返回绝对方向。net.minecraft.nbt.NbtAccounterdefaultQuota- 一个最大分配 2 MiB 的计数器。uncompressedQuota- 一个最大分配 100 MiB 的计数器。
net.minecraft.network.chat.MutableComponent#withoutShadow、Style#withoutShadow- 从文本中移除阴影。net.minecraft.network.protocol.game.ServerboundPlayerActionPacket$Action#STAB- 玩家执行了刺击动作。net.minecraft.network.syncher.EntityDataSerializers#HUMANOID_ARM- 人形生物的主手。net.minecraft.resources.Identifier#toShortString- 返回位置的字符串。如果命名空间是minecraft,则省略。net.minecraft.serverMinecraftServergetServerActivityMonitor- 返回发送服务器活动通知的监视器。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.SchemaBOOL_OR_INT_SCHEMA- 一个可以是布尔值或整数的字段的模式。typedCodec- 返回模式的编解码器。info- 返回模式的副本。
net.minecraft.server.levelChunkMap#getChunkDataFixContextTag- 返回区块数据的数据修复标签。ServerLevelgetDayCount- 获取经过的天数。canSpreadFireAround- 火是否可以在给定的方块位置周围蔓延。
net.minecraft.server.networkEventLoopGroupHolder- 一个用于管理与某个端点(无论是本地还是基于套接字)通信的事件循环和通道的持有者。ServerGamePacketListenerImpl#resetFlyingTicks- 重置玩家已飞行的刻数。
net.minecraft.server.notificationsNotificationService#serverActivityOccurred- 通知管理服务器活动已发生。ServerActivityMonitor- 发送服务器活动通知的监视器。
net.minecraft.utilARGBsrgbToLinearChannel- 将 sRGB 值转换为线性颜色空间。linearToSrgbChannel- 将线性值转换为 sRGB 颜色空间。meanLinear- 使用线性颜色空间计算四个值的平均值,然后将其转换回 sRGB。addRgb- 添加 RGB 通道,使用第一个值的 alpha。subtractRgb- 减去 RGB 通道,使用第一个值的 alpha。multiplyAlpha- 将 alpha 值乘入提供的 ARGB 值。linearLerp- 通过转换为线性颜色空间来线性插值颜色。white、black- 具有提供 alpha 的颜色。alphaBlend- 混合两种颜色及其 alpha 值。vector4fFromARGB32- 将 ARGB 值转换为四个浮点数。
Ease- 一个充满缓动函数的实用工具。ExtraCodecsNON_NEGATIVE_LONG、POSITIVE_LONG- 具有列出约束的长整数。longRange- 一个验证其是否在提供范围内的长整数编解码器。STRING_RGB_COLOR、STRING_ARGB_COLOR- 一个允许以十六进制字符串形式表示 (A)RGB 值的编解码器。MAX_PROPERTY_NAME_LENGTH、MAX_PROPERTY_VALUE_LENGTH、MAX_PROPERTY_SIGNATURE_LENGTH、MAX_PROPERTIES- 与序列化属性映射相关的常量。
Mthcube- 对数字进行立方。chessboardDistance- 计算两对坐标之间的绝对最大差值;返回较大的轴差。
SpecialDates- 一个包含 Mojang 更改某些行为或渲染的日期的实用工具。TriStateCODEC- 三态布尔值的编解码器。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.worldLockCode#canUnlock- 给定的玩家是否可以解锁此代码。Stopwatch- 一个包含创建时间和已用时间的记录。Stopwatches- 一个用于启动、管理和停止秒表的跟踪器。
net.minecraft.world.effectMobEffects#BREATH_OF_THE_NAUTILUS- 防止用户在水下失去空气。MobEffectUtil#shouldEffectsRefillAirsupply- 实体是否具有在液体中补充空气供应的效果。
net.minecraft.world.entityEntitygetHeadLookAngle- 计算头部旋转的视图向量。updateDataBeforeSync- 在同步到客户端之前更新实体中存储的数据。computeSpeed- 计算实体的最后已知速度和位置。getKnownSpeed- 获取实体的最后已知速度。hasMovedHorizontallyRecently- 如果最后已知速度的水平距离大于 0,更具体地说是误差范围。
EntityProcessor- 加载实体时的后处理器。EntityEvent#KINETIC_HIT- 当实体被动能武器击中时触发的事件。HumanoidArm#STREAM_CODEC- 手臂枚举的网络编解码器。LivingEntityDEFAULT_KNOCKBACK- 击中时应用于实体的默认击退。itemSwapTicker- 交换物品时花费的时间。recentKineticEnemies- 最近使用动能武器攻击的攻击者。lungeForwardMaybe- 应用冲刺效果。causeExtraKnockback- 对击退应用乘法力。wasRecentlyStabbed、rememberStabbedEntity- 处理被动能武器刺中的敌人。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.MemoryModuleTypeCHARGE_COOLDOWN_TICKS- 冲刺攻击后的冷却刻数。ATTACK_TARGET_COOLDOWN- 攻击目标前的冷却刻数。
net.minecraft.world.entity.ai.sensing.TemptingSensor#forAnimal- 一个传感器,特别处理动物实体,检查所需物品是否是食物。net.minecraft.world.entity.animal.camelCamelgetDashingSound、getDashReadySound- 骆驼冲刺声音。getStandUpSound、getSitDownSound- 骆驼站/坐声音。getSaddleSound- 骆驼马鞍声音。
CamelHusk- 骆驼干尸实体。
net.minecraft.world.entity.animal.equine.AbstractHorse#isMobControlled- 生物是否可以控制这匹马。net.minecraft.world.entity.animal.nautilusAbstractNautilus- 鹦鹉螺实体的核心。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.PlayercannotAttackWithItem- 检查玩家是否无法使用该物品攻击。getItemSwapScale- 返回用于物品交换动画的标量。resetOnlyAttackStrengthTicker- 重置攻击强度Tick器。openNautilusInventory- 打开交互的鹦鹉螺的库存。applyPostImpulseGraceTime、isInPostImpulseGraceTime- 处理脉冲之间的宽限期。
net.minecraft.world.food.FoodData#hasEnoughFood- 当前食物水平是否大于 6 饥饿值(或三个完整的饥饿条)。net.minecraft.world.inventoryAbstractMountInventoryMenu- 坐骑的库存菜单。NautilusInventoryMenu- 鹦鹉螺的库存菜单。
net.minecraft.world.itemHoneycombItem#WAXED_RECIPES- 打蜡方块到其配方类别和名称的映射。Item$Propertiesspear- 添加矛组件。nautilusArmor- 添加鹦鹉螺盔甲组件。
ItemStack#matchesIgnoringComponents- 堆栈是否匹配,忽略所有匹配谓词的组件。ItemUseAnimationTRIDENT- 三叉戟使用动画。hasCustomArmTransform- 动画是否提供自定义的手臂变换。
net.minecraft.world.item.enchantmentEnchantment#doLunge- 应用穿刺后攻击效果。EnchantmentEffectComponents#POST_PIERCING_ATTACK- 穿刺攻击后应用的效果。EnchantmentHelper#doLungeEffects- 在冲刺时应用效果。LevelBasedValue$Exponent- 应用给定基数和指数的指数。
net.minecraft.world.item.enchantment.effectsApplyEntityImpulse- 一个实体效果,在视角方向添加一个冲量。ApplyExhaustion- 一个实体效果,如果玩家正在使用附魔物品,则应用食物消耗。ScaleExponentially- 一个值效果,将值乘以某个数的指数次幂。
net.minecraft.world.levelChunk#isValid- 区块位置是否在允许的最大世界坐标内(在 3000 万方块半径内)。CollisionGetternoEntityCollision- 实体在给定边界内是否不与另一个实体碰撞。noBorderCollision- 实体在给定边界内是否不与世界边界碰撞。
Level#isInValidBounds- 方块位置是否不在允许的最大世界坐标外(Y 轴为建筑高度,XZ 轴为 3000 万方块半径)。MoonPhase- 一个表示月相的枚举。
net.minecraft.world.level.border.WorldBorder$MovingBorderExtent#getPreviousSize- 获取边界的先前大小。net.minecraft.world.level.chunk.storageIOWorker#STORE_EMPTY- 一个提供的null标签。LegacyTagFixer- 一个处理如何升级标签的接口,例如对于区块。SimpleRegionStorageisOldChunkAround- 来自先前版本的区块是否仍然存在于此版本中。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.Vec3offsetRandomXZ- 在 XZ 方向上按随机量偏移点。rotation- 计算向量的旋转。applyLocalCoordinatesToRotation- 将相对于向量当前旋转的分量相加。isFinite- 返回向量的所有分量是否为有限值(不是 NaN 或无穷大)。
net.minecraft.world.scoresScoreboardpackPlayerTeams- 将玩家队伍打包成可序列化的格式。packObjectives- 将目标打包成可序列化的格式。packDisplaySlots- 将显示槽位打包成可序列化的格式。
ScoreboardSaveDatagetData、setData- 处理打包的记分板。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.VertexConsumeraddVertex、addVertexWith2DPose现在接受其参数的接口、“只读”变体(例如,Vector3f->Vector3fc)putBulkData不再接受最后的boolean来读取缓冲区数据以确定初始颜色
com.mojang.mathOctahedralGroupfromXYAngles->Quadrant#fromXYAnglespermute->SymmetricGroup3#permuteAxis
SymmetricGroup3permutation->permutepermuteVector->OctahedralGroup#rotate
Transformation现在接受其参数的接口、“只读”变体(例如,Vector3f->Vector3fc)- 这也适用于参数获取器方法
net.minecraftFileUtil#isValidStrictPathSegment->containsAllowedCharactersOnly,现在是私有的- 被
isValidPathSegment取代
- 被
MinecraftdisconnectWithProgressScreen现在接受一个boolean,表示是否停止声音引擎disconnect现在接受一个boolean,表示是否停止声音引擎
SharedConstantsDEBUG_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_LEVELS、VISUALIZE_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.clientCamerasetup现在接受Level而不是BlockGetterget*已被其记录替代(例如,getEntity->entity)Vector3f返回值被Vector3fc取代
GraphicsStatus->GraphicsPreset,不是一对一KeyMapping现在有一个接受排序顺序的重载MouseHandler#lastClickTime->lastClick,现在是私有的,不是一对一OptionInstance$OptionInstanceSliderButton现在实现ResettableOptionWidgetOptionsgraphicsMode->graphicsPreset、applyGraphicsPresetshowNowPlayingToast->musicToast,不是一对一
net.minecraft.client.data.modelsEquipmentAssetProvider#humanoidAndHorse->humanoidAndMountArmorItemModelGeneratorsgetSpans->getSideFaces,不是一对一$SpanFacing->$SideDirection,不是一对一$Span->$SideFace,不是一对一
ItemModelOutput#accept现在有一个接受ClientItem$Properties的重载
net.minecraft.client.guiFont#NO_SHADOW->Style#NO_SHADOWGuiGraphicstextHighlight现在接受一个boolean,表示是否渲染背景矩形submitOutline->renderOutline
net.minecraft.client.gui.componentsAbstractButton#handleCursor->handleCursor,现在是 protectedAbstractSliderButtonHANDLE_WIDTH现在是 protectedcanChangeValue、setValue现在是 protected
AbstractWidget#message现在是 protectedCycleButton现在实现ResettableOptionWidgetbuilder现在有一个接受提供的默认值的重载booleanBuilder现在接受一个布尔值来选择默认使用哪个组件$Builder现在接受一个提供的默认值displayOnlyValue(boolean)->displayState,不是一对一
FocusableTextWidget构造函数现在是包私有的,请使用builderOptionsList现在将$AbstractEntry传递到泛型,而不是$EntryaddSmall现在有一个接受OptionInstance的重载$Entry现在扩展$AbstractEntry$OptionEntry类已移除big->$Entry#bigsmall->$Entry#small
StringWidget#clipText现在是公开的静态方法,接受Font
net.minecraft.client.gui.components.debugDebugScreenEntryListtoggleF3Visible->toggleDebugOverlaysetF3Visible->setOverlayVisibleisF3Visible->isOverlayVisible
DebugScreenEntryStatus#IN_F3->IN_OVERLAY
net.minecraft.client.gui.components.debugchart.AbstractDebugChart#COLOR_GREY->CommonColors#TEXT_GRAYnet.minecraft.client.gui.components.toasts.ToastManagercreateNowPlayingToast->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.screensDeathScreen现在接受LocalPlayerScreen现在有一个接受要使用的Minecraft实例和Font的重载minecraft现在是 finalfont现在是 finalinit(Minecraft, int, int)->init(int, int)resize(Minecraft, int, int)->init(int, int)handleComponentClicked->ChatScreen#handleComponentClicked,现在是私有的handleClickEvent已移至其关联的类,而不是一个超接口(例如,BookViewScreen#handleClickEvent)
net.minecraft.client.gui.screens.advancementsAdvancementsScreen#renderWindow现在接受鼠标 XYintAdvancementTab#drawTab现在接受鼠标 XYint
net.minecraft.client.gui.screens.debug.DebugOptionsScreen$OptionList现在是公开的net.minecraft.client.gui.screens.inventoryAbstractCommandBlockEditScreen#populateAndSendPacket不再接受BaseCommandBlockAbstractContainerScreen#renderSlots、renderSlot现在接受鼠标 XYintCreativeModeInventoryScreen#renderTabButton现在接受鼠标 XYintEffectsInInventory#renderEffects->renderHorseInventoryScreen现在扩展AbstractMountInventoryScreenMinecartCommandBlockEditScreen现在接受MinecartCommandBlock而不是BaseCommandBlock
net.minecraft.client.gui.screens.multiplayer.ServerSelectionList$OnlineServerEntry现在实现SelectableEntrynet.minecraft.client.gui.screens.packs.TransferableSelectionList$PackEntry现在实现SelectableEntrynet.minecraft.client.gui.screens.recipebookRecipeBookComponent#initFilterButtonTextures->getFilterButtonTextures,不是一对一RecipeBookTabButton现在实现ImageButton而不是StateSwitchingButton- 构造函数现在接受 XY 位置以及
Button$OnPress消费者
- 构造函数现在接受 XY 位置以及
net.minecraft.client.gui.screens.worldselection.WorldSelectionList$WorldListEntry不再是静态的,现在实现SelectableEntrynet.minecraft.client.modelAnimationUtilsanimateCrossbowCharge现在接受float而不是intanimateZombieArms现在接受UndeadRenderState而不是两个float
HumanoidModelsetupAttackAnimation不再接受floatgetArm现在从 protected 变为 public
net.minecraft.client.model.geom.ModelPart#getExtentsForGui现在接受Consumer<Vector3fc>而不是集合net.minecraft.client.model.geom.builders.UVPair现在是一个记录net.minecraft.client.multiplayerMultiPlayerGameMode#isAlwaysFlying->isSpectatorServerStatusPinger#pingServer现在接受一个EventLoopGroupHolder
net.minecraft.client.rendererCloudRenderer#render现在接受游戏时间longDynamicUniforms#writeTransform、$Transform不再接受线宽floatGameRenderer#setPanoramicMode->setPanoramicScreenshotParameters,不是一对一GlobalSettingsUniform#update现在接受Camera以及是否使用旋转网格超采样(RGSS)ItemBlockRenderTypes#setFancy->setCutoutLeavesItemInHandRenderer不再接受ItemRendererLevelRenderer#isSectionCompiled->isSectionCompiledAndVisibleRenderPipelinesLINE_STRIP->LINES或LINES_TRANSLUCENT,不是一对一DEBUG_LINE_STRIP->DEBUG_POINTS,不是一对一
RenderTypeLINE_STRIP、lineStrip->RenderTypes#LINES、LINES_TRANSLUCENT、linesTranslucent;不是一对一debugLineStrip->debugPoint,不是一对一
SkyRenderer现在接受TextureManager和AtlasManagerextractRenderState现在接受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.blockentityBannerRenderer#getExtents现在接受Consumer<Vector3fc>而不是集合BedRenderer#getExtents现在接受Consumer<Vector3fc>而不是集合BellRenderer#BELL_RESOURCE_LOCATION->BELL_TEXTUREDecoratedPotRenderer#getExtents现在接受Consumer<Vector3fc>而不是集合EnchantTableRenderer#BOOK_LOCATION->BOOK_TEXTUREShulkerBoxRenderer#getExtents现在接受Consumer<Vector3fc>而不是集合TestInstanceRenderer不再接受BlockEntityRendererProvider$Context
net.minecraft.client.renderer.blockentity.state.BlockEntityWithBoundingBoxRenderState$InvisibleBlockType$STRUCUTRE_VOID->STRUCTURE_VOIDnet.minecraft.client.renderer.chunk.ChunkSectionLayer#textureView->texture,不是一对一net.minecraft.client.renderer.entity.EntityRenderDispatcher不再接受ItemRenderernet.minecraft.client.renderer.entity.layersCarriedBLockLayer不再接受BlockRenderDispatcherIronGolemFlowerLayer不再接受BlockRenderDispatcherItemInHandLayer#submitArmWithItem现在接受持有的ItemStack
net.minecraft.client.renderer.entity.stateArmedEntityRenderState*HandItem->*HandItemState、*HandItemStack;不是一对一extractArmedRenderState现在接受部分刻float
HorseRenderState#bodyArmorItem->EquineRenderState#bodyArmorItemHumanoidRenderStateattackTime->ArmedEntityRenderState#attackTimeticksUsingItem现在是一个浮点数
IllagerRenderState现在扩展UndeadRenderStateticksUsingItem现在是一个浮点数
ZombieRenderState现在扩展UndeadRenderStateZombifiedPiglinRenderState现在扩展UndeadRenderState
net.minecraft.client.renderer.fog.FogRenderer#setupFog不再接受booleannet.minecraft.client.renderer.fog.environmentAtmosphericFogEnvironment现在扩展FogEnvironment而不是AirBasedFogEnvironmentFogEnvironment#setupFog不再接受Entity和BlockPos,而是接受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而不是intnet.minecraft.client.resources.SplashManagerprepare现在返回Component列表而不是字符串apply现在接受Component列表而不是字符串
net.minecraft.client.resources.model.BlockModelRotation现在是一个类by->get,不是一对一
net.minecraft.client.resources.soundsRidingHappyGhastSoundInstance->RidingEntitySoundInstance,不是一对一RidingMinecartSoundInstance现在扩展RidingEntitySoundInstance而不是AbstractTickableSoundInstance- 构造函数现在接受
SoundEvent、最小和最大音量,以及放大器
- 构造函数现在接受
SimpleSoundInstance#forMusic不再接受音量
net.minecraft.client.soundsSoundEngine不再接受MusicManagerupdateCategoryVolume->refreshCategoryVolumesetVolume->updateCategoryVolume,不是一对一
SoundManager不再接受MusicManagerupdateSourceVolume->refreshCategoryVolumesetVolume->updateCategoryVolume,不是一对一
net.minecraft.gametest.framework.GameTestHelperspawn现在有一个接受EntitySpawnReason或三个int作为位置的重载assetTrue、assetFalse、assertValueEqual现在有一个接受String而不是Component的重载assertEntityData现在有一个接受AABB边界框的重载getRelativeBounds现在是公开的assertEntityPosition->assertEntityPresent,不是一对一
net.minecraft.nbtCompoundTag#remove现在返回被移除的标签NbtUtils#getDataVersion现在有一个只接受CompoundTag的重载
net.minecraft.networkConnectionNETWORK_WORKER_GROUP->EventLoopGroupHolder#NIO,不是一对一NETWORK_EPOLL_WORKER_GROUP->EventLoopGroupHolder#EPOLL,不是一对一LOCAL_WORKER_GROUP->EventLoopGroupHolder#LOCAL,不是一对一connectToServer、connect现在接受EventLoopGroupHolder而不是boolean
FriendlyByteBufwriteVector3f现在接受Vector3fc而不是Vector3fwriteQuaternion现在接受Quaternionfc而不是QuaternionfDEFAULT_NBT_QUOTA->NbtAccounter#DEFAULT_NBT_QUOTA
net.minecraft.network.codecByteBufCodecsVECTOR3F现在使用Vector3fc而不是Vector3fQUATERNIONF现在使用Quaternionfc而不是Quaternionf
StreamCodec#composite现在有十个和十二个参数变体
net.minecraft.network.chatComponentUtils#mergeStyles现在有一个接受并返回Component的重载MutableComponent现在是 final
net.minecraft.network.protocol.gameClientboundHorseScreenOpenPacket->ClientboundMountScreenOpenPacketClientGamePacketListener#handleHorseScreenOpen->handleMountScreenOpenGamePacketTypes#CLIENTBOUND_HORSE_SCREEN_OPEN->CLIENTBOUND_MOUNT_SCREEN_OPEN
net.minecraft.network.numbersFixedFormat现在是一个记录StyledFormat现在是一个记录
net.minecraft.network.syncher.EntityDataSerializersVECTOR3现在使用Vector3fc而不是Vector3fQUATERNION现在使用Quaternionfc而不是Quaternionf
net.minecraft.serverMinecraftServerisAllowedToEnterPortal->ServerLevel#isAllowedToEnterPortalisSpawningMonsters->ServerLevel#isSpawningMonstersisPvpAllowed->ServerLevel#isPvpAllowedisCommandBlockEnabled->ServerLevel#isCommandBlockEnabledisSpawnerBlockEnabled->ServerLevel#isSpawnerBlockEnabledgetGameRules->ServerLevel#getGameRulesisEpollEnabled->useNativeTransport
ServerScoreboard不再实现其自己的保存数据类型,而是使用打包的ScoreboardSaveDataTYPE->ScoreboardSavedData#TYPE
net.minecraft.server.jsonrpcIncomingRpcMethod现在接受两个泛型,分别用于请求的参数和结果响应$Builder现在有无参数和参数函数的构造函数,取代了$Factoryresponse、param现在接受它们的Schema
OutgoingRpcMethod$Factory现在接受泛型参数和结果
net.minecraft.server.jsonrpc.apiMethodInfo、$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.levelChunkMap现在扩展SimpleRegionStorage而不是ChunkStorageServerLevel#drop不再返回boolean
net.minecraft.server.network.ServerConnectionListenerSERVER_EVENT_GROUP->EventLoopGroupHolder#NIO,不是一对一SERVER_EPOLL_EVENT_GROUP->EventLoopGroupHolder#EPOLL,不是一对一
net.minecraft.stats.ServerStatsCounter现在接受Path而不是FileparseLocal->parse,不是一对一toJson现在返回JsonElement而不是String
net.minecraft.utilARGB#lerp->srgbLerpExtraCodecs现在使用其泛型的接口、“只读”变体(例如,Vector3f->Vector3fc)MtheaseInOutSine->Ease#inOutSinesin、cos现在接受double而不是floatabsMax现在有使用int或float的重载
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->CODECget、reset现在接受世界种子
net.minecraft.world.entityAvatar#DATA_PLAYER_MAIN_HAND现在使用HumanoidArm泛型而不是字节Entity#hasImpulse->needsSyncEntityType#loadEntityRecursive现在接受EntityProcessor而不是FunctionLivingEntity#invulnerableDuration->INVULNERABLE_DURATIONMob#playAttackSound->LivingEntity#playAttackSoundNeutralMobTAG_ANGER_TIME->TAG_ANGER_END_TIME,不是一对一getRemainingPersistentAngerTime->getPersistentAngerEndTime,不是一对一setRemainingPersistentAngerTime->setTimeToRemainAngry、setPersistentAngerEndTime;第二个不是一对一getPersistentAngerTarget、setPersistentAngerTarget现在处理EntityReference
net.minecraft.world.entity.ai.sensing.SensorType#*_TEMPTATIONS->FOOD_TEMPTATIONS,不是一对一net.minecraft.world.entity.ai.utilGoalUtilsmobRestricted现在接受double而不是intisRestricted现在有一个接受Vec3的重载
LandRandomPosgetPosAway现在有一个接受额外double作为起始/结束弧度的重载generateRandomPosTowardDirection现在接受double而不是int
RandomPosgenerateRandomDirectionWithinRadians现在接受double作为起始/结束弧度generateRandomPosTowardDirection现在接受double而不是int
net.minecraft.world.entity.animal.equine.AbstractHorse#getInventorySize->AbstractMountInventoryMenu#getInventorySizenet.minecraft.world.entity.monster.Monster#checkMonsterSpawnRules现在将其类型泛型扩展为Mob而不是Monsternet.minecraft.world.entity.monster.skeleton.Bogged#*_ATTACK_INTERVAL->AbstractSkeleton#INCREASED_*_ATTACK_INTERVALnet.minecraft.world.entity.monster.zombieHusk#checkHuskSpawnRules->Monster#checkSurfaceMonsterSpawnRules,不是一对一ZombiedoUnderWaterConversion现在接受ServerLevelconvertToZombieType现在接受ServerLevel
net.minecraft.world.entity.npc.villagerAbstractVillagerupdateTrades现在接受ServerLeveladdOffersFromItemListings现在接受ServerLevel
Villager#shouldRestock现在接受ServerLevelVillagerTrades$ItemListing#getOffer现在接受ServerLevel
net.minecraft.world.entity.player.PlayeropenMinecartCommandBlock现在接受MinecartCommandBlock而不是BaseCommandBlocksweepAttack->doSweepAttack,现在是私有的,不是一对一respawn->LocalPlayer#respawnCLIENT_LOADED_TIMEOUT_TIME->ServerGamePacketListenerImpl#CLIENT_LOADED_TIMEOUT_TIMEclientLoadedTimeoutTimer、tickClientLoadTimeout->ServerGamePacketListenerImpl#tickClientLoadTimeouthasClientLoaded->ServerGamePacketListenerImpl#hasClientLoadedsetClientLoaded->ServerGamePacketListenerImpl#markClientLoaded、markClientUnloadedAfterDeath、restartClientLoadTimerAfterRespawn;不是一对一
net.minecraft.world.entity.projectile.Projectile构造函数现在是protected而不是包私有的net.minecraft.world.entity.vehicle.VehicleEntity#shouldSourceDestroy现在是protected而不是包私有的net.minecraft.world.entity.vehicle.minecartAbstractMinecart现在接受ServerLevelMinecartCommandBlock$MinecartCommandBase现在是包私有的
net.minecraft.world.inventory.HorseInventoryMenu现在扩展AbstractMountInventoryMenunet.minecraft.world.item.component.ItemAttributeModifiers#compute现在接受Attribute持有者net.minecraft.world.item.enchantment.effects.PlaySoundEffect现在接受一个声音事件列表而不是单个net.minecraft.world.levelBaseCommandBlockperformCommand现在接受ServerLevel而不是LevelonUpdated现在接受ServerLevelcreateCommandSourceStack现在接受ServerLevel$CloseableCommandBlockSource现在接受ServerLevel,其构造函数是 protected
CollisionGetter#noBlockCollision现在有一个接受额外boolean的重载,表示是否检查液体碰撞。Level#getGameTime->LevelAccessor#getGameTimeLevelAccessor#getCurrentDifficultyAt->ServerLevelAccessor#getCurrentDifficultyAtLevelTimeAccess#getMoonPhase现在返回MoonPhase而不是int
net.minecraft.world.level.biomeAmbientAdditionsSettings现在是一个记录AmbientMoodSettings现在是一个记录AmbientParticleSettings现在是一个记录
net.minecraft.world.level.block.entity.BaseContainerBlockEntity#canUnlock->sendChestLockedNotifications,不是一对一net.minecraft.world.level.borderBorderChangeListener#onLerpSize现在接受一个额外的long作为游戏时间WorldBorder现在可以接受WorldBorder$SettingsgetMin*、getMax*现在有一个接受部分刻float的重载lerpSizeBetween现在接受一个额外的long作为游戏时间applySettings->applyInitialSettings,不是一对一- 原始行为可以通过将设置传递给构造函数来复制
$BorderExtent#getMin*、getMax*现在接受部分刻float
net.minecraft.world.level.chunk.storageRecreatingSimpleRegionStorage现在接受一个提供的LegacyTagFixerSimpleRegionStorage现在接受一个提供的LegacyTagFixerwrite现在有一个接受提供的CompoundTag的重载upgradeChunkTag现在有一个接受可为空的标签上下文的重载
net.minecraft.world.level.dimension.DimensionTypeMOON_PHASES现在是一个MoonPhase数组并且是私有的moonPhase现在返回MoonPhase而不是int
net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler现在实现LegacyTagFixer- 构造函数现在接受
DataFixer removeIndex->LegacyTagFixer#markChunkDoneupdateFromLegacy现在是私有的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.storageDimensionDataStorage不再接受SavedData$ContextFileNameDateFormatter#create->FORMATTERLevelStorageSourceUNCOMPRESSED_NBT_QUOTA->NbtAccounter#UNCOMPRESSED_NBT_QUOTA,现在是public$LevelDirectory#corruptedDataFile、rawDataFile现在接受ZonedDateTime而不是LocalDateTime
net.minecraft.world.level.storage.loot.LootContext$BlockEntityTarget现在实现LootContextArg$SimpleGettergetParam->contextParam
$EntityTarget现在实现LootContextArg$SimpleGettergetParam->contextParam
$ItemStackTarget现在实现LootContextArg$SimpleGettergetParam->contextParam
net.minecraft.world.level.storage.loot.functionsCopyComponentsFunction$*Source->$DirectSource,不是一对一$Source->LootContextArg$Getter,不是一对一
CopyNameFunction#copyName现在接受LootContextArg而不是$Source$Source->LootContextArg,不是一对一
FilteredFunction现在接受一个可选的通过和失败的LootItemFunction而不是仅仅一个修改器- 该函数现在可以通过
$Builder通过filtered构建
- 该函数现在可以通过
net.minecraft.world.phys.Vec3现在接受Vector3fc而不是Vector3fnet.minecraft.world.phys.shapes.Shapes#rotateHorizontal、rotateAll、rotateAttachFace现在有接受OctahedralGroup的重载net.minecraft.world.scoresScore现在有一个用于$Packed值的公共构造函数MAP_CODEC->Score$Packed及其$Packed#MAP_CODEC
Scoreboard$PackedScore#score现在接受Score$Packed而不是ScoreScoreboardSavedData现在接受ScoreboardSaveData$Packed而不是ScoreboardFILE_ID合并到类型中loadFrom->ServerScoreboard#loadpack->ServerScoreboard#store,现在是私有的,不是一对一
移除列表
com.mojang.blaze3d.vertex.VertexFormat$Mode#LINE_STRIPnet.minecraft.Util#lastOfnet.minecraft.clientMinecraft#useFancyGraphicsGuiMessage#iconStringSplitterformattedIndexByWidth、componentStyleAtWidthsplitLines(FormattedText, int, Style, FormattedText)
net.minecraft.client.gui.Font#wordWrapHeight(String, int)net.minecraft.client.gui.componentsCycleButtononOffBuilder()$Builder#withInitialValue
StateSwitchingButton
net.minecraft.client.gui.screens.inventoryEffectsInInventory#renderTooltipInventoryScreen#renderEntityInInventory
net.minecraft.client.gui.screens.packs.PackSelectionScreen#clearSelectednet.minecraft.client.player.LocalPlayer#USING_ITEM_SPEED_FACTORnet.minecraft.client.rendererItemModelGenerator#createOrExpandSpanGpuWarnlistManager#dismissWarningAndSkipFabulous、isSkippingFabulousRenderPipelinesDEBUG_STRUCTURE_QUADS、DEBUG_SECTION_QUADS
SkyRenderer#initTextures
net.minecraft.client.renderer.fog.environmentAirBasedFogEnvironmentDimensionOrBossFogEnvironmentFogEnvironment#onNotApplicable
net.minecraft.client.resources.model.BlockModelRotation#actualRotationnet.minecraft.gametest.framework.GameTestHelper#setNight、setDayTimenet.minecraft.network.FriendlyByteBuf#readDate、writeDatenet.minecraft.serverMinecraftServer#hasGuiServerScoreboard#createData、addDirtyListener
net.minecraft.server.jsonrpc.IncomingRpcMethod$Factorynet.minecraft.server.jsonrpc.methods.IllegalMethodDefinitionExceptionnet.minecraft.server.jsonrpc.security.AuthenticationHandler#AUTH_HEADERnet.minecraft.utilDebugBufferLazyLoadedValue
net.minecraft.util.thread.NamedThreadFactorynet.minecraft.world.entity.Mob#isSunBurnTicknet.minecraft.world.entity.animal.armadillo.ArmadilloAi#getTemptationsnet.minecraft.world.entity.animal.axolotl.AxolotlAi#getTemptationsnet.minecraft.world.entity.animal.camel.CamelAi#getTemptationsnet.minecraft.world.entity.animal.equine.ZombieHorse#checkZombieHorseSpawnRules- 请改用
Monster#checkMonsterSpawnRules
- 请改用
net.minecraft.world.entity.animal.goat.GoatAi#getTemptationsnet.minecraft.world.entity.animal.sniffer.SnifferAi#getTemptationsnet.minecraft.world.entity.player.Player#playNotifySoundnet.minecraft.world.entity.raid.Raid#TICKS_PER_DAYnet.minecraft.world.levelBaseCommandBlockgetLevelgetUsedBy、getPosition
Level#TICKS_PER_DAY
net.minecraft.world.level.border.WorldBorder$Settings#toWorldBorder- 请改用
WorldBorder构造函数
- 请改用
net.minecraft.world.level.chunk.storageChunkStorageRecreatingChunkStorage
net.minecraft.world.level.saveddata.SavedData$Contextnet.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.BuiltInRegistries、RegistriesLOOT_POOL_ENTRY_TYPE现在持有LootPoolEntryContainer的映射编解码器,而不是LootPoolEntryTypeLOOT_FUNCTION_TYPE现在持有LootItemFunction的映射编解码器,而不是LootItemFunctionTypeLOOT_CONDITION_TYPE现在持有LootItemCondition的映射编解码器,而不是LootItemConditionTypeLOOT_NUMBER_PROVIDER_TYPE现在持有NumberProvider的映射编解码器,而不是LootNumberProviderTypeLOOT_NBT_PROVIDER_TYPE现在持有NbtProvider的映射编解码器,而不是LootNbtProviderTypeLOOT_SCORE_PROVIDER_TYPE现在持有ScoreboardNameProvider的映射编解码器,而不是LootScoreProviderTypeFLOAT_PROVIDER_TYPE现在持有FloatProvider的映射编解码器,而不是FloatProviderTypeINT_PROVIDER_TYPE现在持有IntProvider的映射编解码器,而不是IntProviderType
net.minecraft.util.valueproviders现在将CODEC字段重命名为MAP_CODECFloatProvider的子类型现在都是记录IntProvider的子类型,除了WeightedListInt,现在都是记录FloatProvider现在从class变为interfaceCODEC->FloatProviders#CODECcodec->FloatProviders#codecgetType->codec,不是一对一getMinValue->mingetMaxValue->max
FloatProviders- 所有要注册的原版浮点数提供者。FloatProviderType接口已移除- 所有单例字段已被移除,请改用每个类中的映射编解码器
codec->FloatProvider#codec
IntProvider现在从class变为interfaceCODEC->IntProviders#CODECNON_NEGATIVE_CODEC->IntProviders#NON_NEGATIVE_CODECPOSITIVE_CODEC->IntProviders#POSITIVE_CODECcodec->IntProviders#codecvalidateCodec->IntProviders#validateCodecgetMinValue->minInclusivegetMaxValue->maxInclusivegetType->codec,不是一对一
IntProviders- 所有要注册的原版整数提供者。IntProviderType接口已移除- 所有单例字段已被移除,请改用每个类中的映射编解码器
codec->IntProvider#codec
net.minecraft.world.level.storage.loot.entries现在将CODEC字段重命名为MAP_CODECLootPoolEntries的所有单例字段已被移除- 应改用每个类中的映射编解码器
bootstrap- 注册战利品池条目。
LootPoolEntryContainer#getType->codec,不是一对一LootPoolEntryType记录已移除
net.minecraft.world.level.storage.loot.functions现在将CODEC字段重命名为MAP_CODECLootItemFunction#getType->codec,不是一对一LootItemFunctions的所有单例字段已被移除- 应改用每个类中的映射编解码器
bootstrap- 注册战利品物品函数。
LootItemFunctionType记录已移除
net.minecraft.world.level.storage.loot.predicates现在将CODEC字段重命名为MAP_CODECLootItemCondition#getType->codec,不是一对一LootItemConditions的所有单例字段已被移除- 应改用每个类中的映射编解码器
bootstrap- 注册战利品物品条件。
LootItemConditionType记录已移除
net.minecraft.world.level.storage.loot.providers.nbt现在将CODEC字段重命名为MAP_CODECLootNbtProviderType记录已移除NbtProvider现在实现LootContextUsergetType->codec,不是一对一
NbtProviders的所有单例字段已被移除- 应改用每个类中的映射编解码器
bootstrap- 注册 NBT 提供者。
LootItemConditionType记录已移除
net.minecraft.world.level.storage.loot.providers.number现在将CODEC字段重命名为MAP_CODECLootNumberProviderType记录已移除NumberProvider#getType->codec,不是一对一NumberProviders的所有单例字段已被移除- 应改用每个类中的映射编解码器
bootstrap- 注册数字提供者。
net.minecraft.world.level.storage.loot.providers.score现在将CODEC字段重命名为MAP_CODECLootScoreProviderType记录已移除ScoreProvider现在实现LootContextUsergetType->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而不是CriterionValidatornet.minecraft.advancements.criterionContextAwarePredicate现在实现ValidatableCriterionValidator->ValidationContextSource和ValidatableValidatable包含validate*方法ValidationContextSource持有上下文和报告器
net.minecraft.world.item.enchantmentConditionalEffect现在实现ValidatableconditionCodec被加载后调用validate取代
TargetedConditionalEffect现在实现Validatable
net.minecraft.world.level.storage.lootIntRange现在实现LootContextUsergetReferencedContextParams被validate取代
LootContext$VisitedEntry泛型现在必须扩展ValidatableLootContextUser现在实现ValidatableLootDataType泛型现在必须扩展Validatable- 构造函数现在接受
$ContextGetter而不是$Validator runValidation现在接受ValidationContextSource而不是ValidationContext- 还有一个接受
HolderLookup而不是键值对的重载
- 还有一个接受
createSimpleValidator、createLootTableValidator、$Validator被Validatable取代$ContextGetter- 获取某个值的ContextKeySet。
- 构造函数现在接受
LootPool现在实现ValidatableLootTable现在实现ValidatableValidatable- 一个接口,处理其实例在给定上下文中的验证。ValidationContextforField- 为给定字段创建上下文。forIndexedField- 为列表中的给定条目创建上下文。forMapField- 为映射中的给定键创建上下文。setContextKeySet已移除
ValidationContextSource- 进行验证的定义上下文的源。
net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer现在实现Validatablenet.minecraft.world.level.storage.loot.functionsSetAttributesFunction$Modifier现在实现LootContextUserSetStewEffectFunction$EffectEntry现在实现LootContextUser
数据包村民交易
村民交易现已从其原始的基于映射的设置变为数据生成的注册表。虽然初步印象可能使该系统看起来更受限,但实际上它同样具有可扩展性,尽管方式相当复杂,因为交易本身就是一个战利品表,用于确定商人可以提供哪些 MerchantOffer。为了便于理解,本节将介绍交易重写的基础知识,以及如何将每个先前的物品列表转换为 VillagerTrade。
理解交易格式
所有交易都表示为 VillagerTrade,其核心是确定商人 wants(想要)什么以及它 gives(给予)什么作为回报。每个交易还可以提供对物品本身或其成本的修改器,或者根据给定条件决定是否可以达成特定交易。每个交易还指定可以进行的交易次数、给予多少经验值,或者与用户声誉相乘的价格倍数。然后通过 getOffer 将 VillagerTrade 转换为 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#addOffersFromItemListings 或 AbstractVillager#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.RegistriesTRADE_SET- 指向持有交易列表的注册表的键。VILLAGER_TRADE- 指向持有单个交易的注册表的键。
net.minecraft.tags.VillagerTradeTags- 村民交易的标签。net.minecraft.world.entity.npc.villagerAbstractVillager#addOffersFromItemListings->addOffersFromTradeSet,接受交易集的键而不是$ItemListing和报价数量;不是一对一VillagerProfession现在接受一个交易员等级到TradeSet的映射getTrades- 返回给定等级的交易集键。
VillagerTrades已被拆分为许多不同的类和实现TRADES、EXPERIMENTAL_TRADES、WANDERING_TRADER_TRADES现在由VillagerProfession#tradeSetsByLevel表示- 由于它们现在是数据包条目,因此存储在其各自的数据包中
TRADES、EXPERIMENTAL_TRADES由data/minecraft/trade_set/<profession>/*表示WANDERING_TRADER_TRADES由data/minecraft/trade_set/wandering_trader/*表示
$DyedArmorForEmeralds->VillagerTrades#dyedItem、addRandomDye;不是一对一$EmeraldForItems->VillagerTrade,不是一对一$EmeraldsForVillagerTypeItem->VillagerTrades#registerBoatTrades,参见用法,不是一对一$EnchantBookForEmeralds->VillagerTrades#enchantedBook,不是一对一$EnchantedItemForEmeralds->VillagerTrades#enchantedItem,不是一对一$ItemListing->VillagerTrade$ItemsAndEmeraldsToItems-> 带有additionalWants的VillagerTrade$ItemsForEmeralds->VillagerTrade,不是一对一$SuspiciousStewForEmerald-> 带有SetStewEffectFunction的VillagerTrade$TippedArrowForItemsAndEmeralds-> 带有SetRandomPotionFunction的VillagerTrade$TreasureMapForEmeralds->VillagerTrades$VillagerExplorerMapEntry,参见用法,不是一对一$TypeSpecificTrade->VillagerTrades#villagerTypeRestriction、villagerTypeHolderSet;不是一对一
net.minecraft.world.item.enchantment.providers.TradeRebalanceEnchantmentProviders接口已移除- 被
TradeRebalanceVillagerTrades、TradeRebalanceRegistries取代
- 被
net.minecraft.world.item.tradingTradeCost- 正在与某个商人交易的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 提供了两种方法来将组件初始化延迟到此类数据组件加载完成之后:delayedComponent 和 delayedHolderComponent。delayedComponent 接受组件类型和一个接受 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.coreHolderareComponentsBound- 组件是否已绑定到持有者。components- 存储在持有者上的对象组件。direct、$Direct现在可以接受DataComponentMap$Reference#bindComponents- 将组件存储在持有者引用上。
Registry#componentLookup- 获取组件到持有者的查找。WritableRegistry#bindTag->bindTags,现在接受一个键到持有者列表的映射,而不是一个映射
net.minecraft.core.componentDataComponentInitializers- 一个处理为组件附加对象初始化数据组件的类。DataComponentLookup- 一个将组件类型映射到使用它的持有者的查找表。DataComponentMap$Builder#addValidator- 为对象上的组件添加验证器。DataComponentPatchget现在接受DataComponentGetter并返回原始组件值$Builder#set现在有一个接受TypedDataComponent可迭代对象的重载
DataComponentsDAMAGE_TYPE现在是一个持有者包装的DamageType,而不是EitherHolder包装的PROVIDES_TRIM_MATERIAL现在是一个持有者包装的TrimMaterial,而不是ProvidesTrimMaterialCHICKEN_VARIANT现在是一个持有者包装的ChickenVariant,而不是EitherHolder包装的ZOMBIE_NAUTILUS_VARIANT现在是一个持有者包装的ZombieNautilusVariant,而不是EitherHolder包装的PROVIDES_BANNER_PATTERNS现在是一个HolderSet,而不是TagKey
net.minecraft.core.registriesBuiltInRegistries#DATA_COMPONENT_INITIALIZERS- 附加到注册表条目的数据组件列表。Registries#componentsDirPath- 注册表中组件的路径目录。
net.minecraft.data.PackOutput#createRegistryComponentPathProvider- 用于组件注册表报告的路径提供者。net.minecraft.data.info.ItemListReport->RegistryComponentsReport,不是一对一net.minecraft.resourcesNetworkRegistryLoadTask- 一个加载任务,处理从网络注册注册表对象和标签,否则从资源注册。RegistryDataLoader$PendingRegistration->RegistryLoadTask$PendingRegistration$RegistryData现在接受一个RegistryValidator而不是一个boolean$RegistryLoadTask->RegistryLoadTask,不是一对一
RegistryValidator- 一个接口,用于验证注册表中的条目,将所有错误存储在映射中。ResourceManagerRegistryLoadTask- 一个加载任务,处理从本地资源管理器注册注册表对象和标签。
net.minecraft.server.ReloadableServerResources#updateStaticRegistryTags->updateComponentsAndStaticRegistryTags,不是一对一net.minecraft.world.itemEitherHolder类已移除ItemCODEC_WITH_BOUND_COMPONENTS- 一个验证组件已绑定的物品编解码器。$PropertiesdelayedComponent- 延迟设置组件,提供HolderLookup$Provider以获取任何动态元素。delayedHolderComponent- 为某个持有者包装的注册表对象延迟设置组件。
ItemStack#validateComponents现在从public变为privateJukeboxPlayable现在持有持有者包装的JukeboxSong,而不是EitherHolder包装的变体JukeboxSong#fromStack不再接受HolderLookup$ProviderSpawnEggItemspawnEntity现在是staticbyId现在返回一个可选的持有者包装的Item,而不是SpawnEggItemeggs已移除getType现在是staticspawnOffspringFromSpawnEgg现在是static
net.minecraft.world.item.componentBlocksAttacks现在持有一个可选的持有者集包装的DamageType,而不是TagKeyDamageResistant现在持有一个持有者集DamageType,而不是TagKeyInstrumentComponent现在持有一个持有者包装的Instrument,而不是EitherHolder包装的变体unwrap已移除
ProvidesTrimMaterial现在持有一个持有者包装的TrimMaterial,而不是EitherHolder包装的变体
net.minecraft.world.item.craftingRecipe#assemble不再接受HolderLookup$ProviderSmithingTrimRecipe#applyTrim不再接受HolderLookup$Provider
net.minecraft.world.item.equipment.trim.TrimMaterials#getFromIngredient已移除net.minecraft.world.level.storage.loot.functions.SetInstrumentFunction、#setInstrumentOptions现在接受持有者集包装的Instrument,而不是TagKeynet.minecraft.world.timeline.Timeline#validateRegistry- 验证每个时间标记仅定义一次。
物品实例与堆栈模板
ItemStack 现在有一个称为 ItemStackTemplate 的不可变实例。与 ItemStack 类似,它包含持有者包装的 Item、它表示的物品数量以及要应用于堆栈的组件的 DataComponentPatch。模板可以通过 create 转换为堆栈,或者如果需要添加额外数据组件,则通过 apply 转换。ItemStack 同样可以通过 ItemStackTemplate#fromNonEmptyStack 转换为模板。现在在需要不可变性的地方(例如,进度、配方等)使用模板代替 ItemStack。它们为网络通信提供了常规的 CODEC、MAP_CODEC 和 STREAM_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.advancementsAdvancement$Builder#display现在接受ItemStackTemplate而不是ItemStackDisplayInfo现在接受ItemStackTemplate而不是ItemStackgetIcon现在返回ItemStackTemplate而不是ItemStack
net.minecraft.advancements.criterionAnyBlockInteractionTrigger#trigger现在接受ItemInstance而不是ItemStackItemPredicate现在实现ItemInstance的谓词而不是ItemStackItemUsedOnLocationTrigger#trigger现在接受ItemInstance而不是ItemStack
net.minecraft.client.particle.BreakingItemParticle$ItemParticleProvider#getSprite现在接受ItemStackTemplate而不是ItemStacknet.minecraft.commands.arguments.itemItemInput现在是一个记录serialize已移除createItemStack不再接受用于检查大小的boolean
ItemParser#parse现在返回ItemResult而不是ItemParser$ItemResult$ItemResult合并到ItemInput
net.minecraft.core.component.predicatesBundlePredicate现在处理ItemInstance的可迭代对象而不是ItemStackContainerPredicate现在处理ItemInstance的可迭代对象而不是ItemStack
net.minecraft.core.particles.ItemParticleOption现在接受ItemStackTemplate而不是ItemStack- 还有一个接受常规
Item的重载 getItem现在返回ItemStackTemplate而不是ItemStack
- 还有一个接受常规
net.minecraft.data.recipesRecipeBuildergetResult已移除defaultId- 使用此构建器制作的配方的默认标识符。getDefaultRecipeId现在接受ItemInstance而不是ItemLike
RecipeProvideroreSmelting、oreBlasting现在接受CookingBookCategoryoreCooking不再接受RecipeSerializer,现在接受CookingBookCategorycookRecipes、simpleCookingRecipe不再接受RecipeSerializershapeless现在接受ItemStackTemplate而不是ItemStack
ShapedRecipeBuilder现在接受ItemStackTemplate作为结果,ItemLike移至重载- 两个构造函数都是
private
- 两个构造函数都是
ShapelessRecipeBuilder现在接受ItemStackTemplate作为结果而不是ItemStackSimpleCookingRecipeBuilder现在接受ItemStackTemplate作为结果,ItemLike移至重载generic不再接受RecipeSerializer,现在接受CookingBookCategoryblasting、smelting现在接受CookingBookCategory
SingleItemRecipeBuilder现在接受ItemStackTemplate作为结果,ItemLike移至重载ItemStackTemplate构造函数是private
SmithingTransformRecipeBuilder现在接受ItemStackTemplate作为结果而不是ItemTransmuteRecipeBuilder现在接受ItemStackTemplate作为结果而不是Holder<Item>- 构造函数是
private transmute现在有一个接受ItemStackTemplate作为结果的重载addMaterialCountToOutput、setMaterialCount- 根据使用的材料数量处理结果堆栈的大小。
- 构造函数是
net.minecraft.network.chat.HoverEvent$ShowItem现在接受ItemStackTemplate而不是ItemStacknet.minecraft.server.dialog.body.ItemBody现在接受ItemStackTemplate而不是ItemStacknet.minecraft.world.entity.LivingEntitydropFromEntityInteractLootTable现在接受ItemInstance而不是ItemStack作为工具dropFromShearingLootTable现在接受ItemInstance而不是ItemStack作为工具
net.minecraft.world.itemBundleItem#getSelectedItemStack->getSelectedItem,现在返回ItemStackTemplate而不是ItemStackItemgetCraftingRemainder现在返回ItemStackTemplate而不是ItemStack$Properties#craftRemainder现在有一个接受ItemStackTemplate的重载
ItemInstance- 一个类型化的物品实例,可以查询物品、大小及其组件。ItemStack现在实现ItemInstanceSINGLE_ITEM_CODEC、STRICT_CODEC、STRING_SINGLE_ITEM_CODEC、SIMPLE_ITEM_CODEC已移除getMaxStackSize->ItemInstance#getMaxStackSize
ItemStackTemplate- 一个包含堆栈不可变组件的记录:物品、数量和组件。
net.minecraft.world.item.componentBundleContents现在接受ItemStackTemplate列表而不是ItemStackitems现在返回ItemStackTemplate列表而不是ItemStack的可迭代对象itemsCopy已移除getSelectedItem- 返回选中物品的堆栈模板,如果没有选中物品则返回null。
ChargedProjectile现在是一个记录- 构造函数接受
ItemStackTemplate列表而不是ItemStack of->ofNonEmptygetItems->itemCopies
- 构造函数接受
ItemContainerContentsstream->allItemsCopyStreamnonEmptyStream->nonEmptyItemCopyStreamnonEmptyItems、nonEmptyItemsCopy->nonEmptyItems,现在返回ItemStackTemplate的可迭代对象而不是ItemStack
UseRemainder现在接受ItemStackTemplate而不是ItemStack
net.minecraft.world.item.craftingAbstractCookingRecipe现在接受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而不是ItemStacknet.minecraft.world.item.enchantment.EnchantmentHelper#getItemEnchantmentLevel现在接受ItemInstance而不是ItemStacknet.minecraft.world.level.block.BlockdropFromBlockInteractLootTable现在接受ItemInstance而不是ItemStackgetDrops现在接受ItemInstance而不是ItemStack
net.minecraft.world.level.block.entity.DecoratedPotBlockEntity#createdDecoratedPotItem->createdDecoratedPotInstancecreateDecoratedPotTemplate创建ItemStackTemplate而不是ItemStack
net.minecraft.world.level.storage.lootLootContext$ItemStackTarget现在为参数获取器实现ItemInstance泛型,而不是ItemStackLootContextArg$ArgCodecBuilder#anyItemStack现在需要一个接受ItemInstance上下文键的函数,而不是ItemStack上下文键
net.minecraft.world.level.storage.loot.parameters.LootContextParams#TOOL现在是ItemInstance上下文键,而不是ItemStack上下文键
序列化器记录与配方信息
配方的实现已略有重做。首先,RecipeSerializer 现在是一个记录,接受用于序列化和反序列化配方的 MapCodec 和 StreamCodec。因此,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 接口中定义的方法访问。因此,可以使用 NormalCraftingRecipe、CustomRecipe、SimpleSmithingRecipe、SingleItemRecipe 和 AbstractCookingRecipe 等类通过实现几个方法来创建新的配方实现。
请注意,这些常见信息类是一种设计理念,您可以根据需要选择实现。只有在构建现有配方子类型时才需要使用它们。
net.minecraft.data.recipesCustomCraftingRecipeBuilder- 一个配方构建器,从某些常见和合成书籍信息创建任意合成配方。RecipeBuilderdetermineBookCategory->determineCraftingBookCategorycreateCraftingCommonInfo- 创建常见的配方信息。createCraftingBookInfo- 创建合成书籍信息。
RecipeUnlockAdvancementBuilder- 用于解锁配方的进度构建器。SpecialRecipeBuilder、special现在接受一个提供的Recipe而不是一个CraftingBookCategory到Recipe的函数unlockedBy- 解锁配方进度所需的条件。
net.minecraft.world.item.craftingAbstractCookingRecipe现在接受Recipe$CommonInfo和$CookingBookInfo而不是 group 和CookingBookCategory$Factory#create现在接受Recipe$CommonInfo和$CookingBookInfo而不是 group 和CookingBookCategory$Serializer被cookingMapCodec、cookingStreamCodec取代$CookingBookInfo- 一个包含配方书常见烹饪信息的记录。
BannerDuplicateRecipe现在接受旗帜Ingredient和ItemStackTemplate结果,而不是CraftingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
BlastingRecipe现在接受Recipe$CommonInfo和$AbstractCookingRecipeCookingBookInfo而不是 group 和CookingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
BookCloningRecipe现在接受源和材料的Ingredient、定义可复制代数的MinMaxBounds$Ints,以及ItemStackTemplate结果,而不是CraftingBookCategoryALLOWED_BOOK_GENERATION_RANGES、DEFAULT_BOOK_GENERATION_RANGES- 书籍代数克隆的范围。MAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
CampfireCookingRecipe现在接受Recipe$CommonInfo和AbstractCookingRecipe$CookingBookInfo而不是 group 和CookingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
CraftingRecipe$CraftingBookInfo- 一个包含配方书常见合成信息的记录。CustomRecipe不再接受任何构造函数参数$Serializer已移除,被其实现的编解码器取代
DecoratedPotRecipe现在接受每侧的Ingredient图案以及ItemStackTemplate结果,而不是CraftingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
DyeRecipe现在接受Recipe$CommonInfo和CraftingRecipe$CraftingBookInfo,以及目标物品和染料的Ingredient和ItemStackTemplate结果,而不是CraftingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
FireworkRocketRecipe现在接受外壳、燃料和星星的Ingredient以及ItemStackTemplate结果,而不是CraftingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
FireworkStarFadeRecipe现在接受目标物品和染料的Ingredient以及ItemStackTemplate结果,而不是CraftingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
FireworkStarRecipe现在接受$Shape到Ingredient的映射;踪迹、闪烁、燃料和染料的Ingredient;以及ItemStackTemplate结果,而不是CraftingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
MapCloningRecipe被TransmuteRecipe取代MapExtendingRecipe现在扩展CustomRecipe而不是ShapedRecipe- 构造函数现在接受地图和材料的
Ingredient以及ItemStackTemplate结果,而不是CraftingBookCategory MAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
- 构造函数现在接受地图和材料的
NormalCraftingRecipe- 一个定义合成配方标准实现的类。RecipeshowNotification、group不再是默认的$BookInfo- 配方书的信息。$CommonInfo- 所有配方的常见信息。
RecipeSerializer现在是一个包含MapCodec和StreamCodec的记录- 注册的条目已移至
RecipeSerializers register已移除
- 注册的条目已移至
RecipeSerializers- 所有配方的原版序列化器。RepairItemRecipe不再接受任何参数INSTANCE- 配方序列化器单例。MAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
ShapedRecipe现在扩展NormalCraftingRecipe而不是实现CraftingRecipe- 构造函数现在接受
Recipe$CommonInfo和CraftingRecipe$CraftingBookInfo而不是 group 和CraftingBookCategory $Serializer->MAP_CODEC、STREAM_CODEC、SERIALIZER;不是一对一
- 构造函数现在接受
ShapelessRecipe现在扩展NormalCraftingRecipe而不是实现CraftingRecipe- 构造函数现在接受
Recipe$CommonInfo和CraftingRecipe$CraftingBookInfo而不是 group 和CraftingBookCategory $Serializer->MAP_CODEC、STREAM_CODEC、SERIALIZER;不是一对一
- 构造函数现在接受
ShieldDecorationRecipe现在接受旗帜和目标物品的Ingredient以及ItemStackTemplate结果,而不是CraftingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
SimpleSmithingRecipe- 一个定义锻造配方标准实现的类。SingleItemRecipe现在接受Recipe$CommonInfo而不是 groupcommonInfo- 配方的常见信息。$Factory#create现在接受Recipe$CommonInfo而不是 group$Serializer->simpleMapCodec、simpleStreamCodec;不是一对一
SmeltingRecipe现在接受Recipe$CommonInfo和AbstractCookingRecipe$CookingBookInfo而不是 group 和CookingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
SmithingTransformRecipe现在扩展SimpleSmithingRecipe而不是实现SmithingRecipe- 构造函数现在接受
Recipe$CommonInfo $Serializer->MAP_CODEC、STREAM_CODEC、SERIALIZER;不是一对一
- 构造函数现在接受
SmithingTrimRecipe现在扩展SimpleSmithingRecipe而不是实现SmithingRecipe- 构造函数现在接受
Recipe$CommonInfo $Serializer->MAP_CODEC、STREAM_CODEC、SERIALIZER;不是一对一
- 构造函数现在接受
SmokingRecipe现在接受Recipe$CommonInfo和AbstractCookingRecipe$CookingBookInfo而不是 group 和CookingBookCategoryMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
StonecutterRecipe现在接受Recipe$CommonInfo而不是 groupMAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
TippedArrowRecipe->ImbueRecipe,不是一对一- 构造函数现在接受
Recipe$CommonInfo和CraftingRecipe$CraftingBookInfo,以及源材料和材料的Ingredient和ItemStackTemplate结果,而不是CraftingBookCategory MAP_CODEC、STREAM_CODEC、SERIALIZER- 配方的序列化器。
- 构造函数现在接受
TransmuteRecipe现在扩展NormalCraftingRecipe而不是实现CraftingRecipe- 构造函数现在接受
Recipe$CommonInfo和CraftingRecipe$CraftingBookInfo,以及处理材料数量并将其添加到结果的MinMaxBounds$Ints和boolean,而不是 group 和CraftingBookCategory $Serializer->MAP_CODEC、STREAM_CODEC、SERIALIZER;不是一对一
- 构造函数现在接受
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_DYES 或 ItemTags#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.RecipeProviderdyedItem- 创建一个染色物品配方。dyedShulkerBoxRecipe- 创建一个染色潜影盒配方。dyedBundleRecipe- 创建一个染色捆绑包配方。
net.minecraft.world.itemBundleItemgetAllBundleItemColors、getByColor已移除
DyeColor#VALUES- 所有染料颜色的列表。DyeItem不再接受DyeColorgetDyeColor、byColor已移除
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.blockBannerBlock#byColor已移除ShulkerBoxBlock#getBlockByColor、getColoredItemStack已移除
世界时钟与时间标记
世界时钟是表示从世界首次加载起每刻增加的时间的对象。这些时钟用作计时器,以正确处理基于时间的事件(例如,当前日期、睡眠)。原版提供了两个世界时钟:一个用于 minecraft:overworld,一个用于 minecraft:the_end。
创建时钟非常简单:只需在 world_clock 中创建一个空的数据包注册表对象。
// 对于某个世界时钟 'examplemod:EXAMPLE_CLOCK'
// JSON 位于 'data/examplemod/world_clock/EXAMPLE_CLOCK.json'
{}
然后,您可以通过 ClockManager 通过 Level#clockManager 或 MinecraftServer#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.multiplayerClientLevelsetTimeFromServer不再接受long白天时间,也不再接受是否滴答白天时间的boolean$ClientLevelData#setDayTime已移除
ClientPacketListener#clockManager- 获取客户端时钟管理器。
net.minecraft.client.renderer.EndFlashState#tick现在接受结束时钟时间而不是游戏时间net.minecraft.commands.arguments.ResourceArgumentgetClock- 根据字符串资源标识符获取世界时钟的引用。getTimeline- 根据字符串资源标识符获取时间线的引用。
net.minecraft.core.registries.Registries#WORLD_CLOCK- 世界时钟的注册表标识符。net.minecraft.gametest.framework.TestEnvironmentDefinition$TimeOfDay->$ClockTime,不是一对一$Timelines- 一个使用时间线列表的测试环境。
net.minecraft.network.protocol.game.ClientboundSetTimePacket现在接受一个时钟到其网络状态的映射,而不是白天时间long和booleannet.minecraft.serverMinecraftServerforceTimeSynchronization->forceGameTimeSynchronization,不是一对一clockManager- 服务器时钟管理器。
net.minecraft.server.level.ServerLevelsetDayTime、getDayCount已移除setEnvironmentAttributes- 设置要使用的环境属性系统。
net.minecraft.world.attribute.EnvironmentAttributeSystem$Builder#addTimelineLayer现在接受ClockManager而不是LongSuppliernet.minecraft.world.clockClockManager- 一个管理器,获取世界时钟已过去的刻数总数。ClockNetworkState- 要在网络上同步的时钟的当前状态。ClockState- 时钟的当前状态,包括总刻数和时钟是否暂停。ClockTimeMarker- 一个跟踪世界时钟某个时间段的标记。ClockTimeMarkers- 所有原版时间标记。PackedClockStates- 一个时钟到其状态的映射,为存储或其他用途而压缩。ServerClockManager- 在服务器端管理世界时钟的滴答。WorldClock- 一个表示某个位置计时键的空记录。WorldClocks- 所有原版世界时钟。
net.minecraft.world.levelLevelgetDayTime->getOverworldClockTime,不是一对一clockManager- 时钟管理器。getDefaultClockTime- 获取当前维度的时钟时间。
LevelReader#getEffectiveSkyBrightness- 使用当前变暗因子获取天空亮度。
net.minecraft.world.level.dimension.DimensionType现在接受一个默认的、持有者包装的WorldClocknet.minecraft.world.level.storageLevelData#getDayTime已移除ServerLevelDatasetDayTime已移除setClockStates、clockStates- 处理世界时钟的当前状态。
net.minecraft.world.level.storage.loot.predicates.TimeCheck现在接受一个持有者包装的WorldClocktime现在接受一个持有者包装的WorldClock$Builder现在接受一个持有者包装的WorldClock
net.minecraft.world.timelineAttributeTrack#bakeSampler现在接受一个持有者包装的WorldClockAttributeTrackSampler现在接受一个持有者包装的WorldClock,以及一个ClockManager而不是用于白天时间获取器的LongSupplierTimeline现在接受一个持有者包装的WorldClock以及一个时间标记到其信息的映射#builder现在接受一个持有者包装的WorldClockgetPeriodCount- 获取在给定时间范围内已发生的周期数。getCurrentTicks现在接受ClockManager而不是LevelgetTotalTicks现在接受ClockManager而不是Levelclock- 返回持有者包装的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现在接受可选的GameRulesnet.minecraft.client.gui.screens.worldselectionCreateWorldCallback现在接受LevelDataAndDimensions$WorldDataAndGenSettings和可选的GameRules,而不是PrimaryLevelDataEditGameRulesScreen->AbstractGameRulesScreen- 实现在
.screens.options.InWorldGameRulesScreen和WorldCreationGameRulesScreen中
- 实现在
WorldOpenFlowscreateLevelFromExistingSettings现在接受LevelDataAndDimensions$WorldDataAndGenSettings和可选的GameRules,而不是WorldDataloadWorldStem现在接受LevelStorageSource$LevelStorageAccess
net.minecraft.client.server.IntegratedServer现在接受可选的GameRulesnet.minecraft.serverMinecraftServer现在接受可选的GameRulesgetGlobalGameRules- 获取主世界维度的游戏规则。getWorldGenSettings- 获取世界的生成设置。getWeatherData- 获取服务器的天气数据。getDataStorage- 获取服务器的保存数据存储。getGameRules- 获取服务器的游戏规则。
WorldStem现在接受LevelDataAndDimensions$WorldDataAndGenSettings而不是WorldData
net.minecraft.server.bosseventsCustomBossEvent现在接受一个UUID作为标识符,以及一个Runnable作为回调getTextId->customIdaddOfflinePlayer已移除getValue->valuegetMax->maxload现在接受UUID标识符以及一个Runnable作为回调
CustomBossEvents现在扩展SavedDatacreate现在接受一个RandomSourcesave、load->TYPE,不是一对一
net.minecraft.server.dedicated.DedicatedServer现在接受可选的GameRulesnet.minecraft.server.levelChunkMap#getChunkDataFixContextTag现在接受一个可选的Identifier而不是ResourceKeyServerBossEvent现在接受一个UUID作为 idsetDirty- 将 boss 事件标记为脏以进行保存。
ServerLevel不再接受RandomSequencessetWeatherParameters->MinecraftServer#setWeatherParametersgetWeatherData- 获取服务器的天气数据。getRandomSequence->MinecraftServer#getRandomSequencegetRandomSequences->MinecraftServer#getRandomSequences
net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner现在接受SavedDataStorage而不是ServerLevelDataMIN_SPAWN_CHANCE现在从private变为public
net.minecraft.world.entity.raid.Raids#TYPE_END、getType已移除net.minecraft.world.levelLevel#prepareWeather已移除LevelSettings现在是一个记录- 构造函数现在接受
$DifficultySettings而不是仅仅Difficulty withDifficultyLock- 带有难度是否锁定的设置。copy- 复制设置。$DifficultySettings- 难度的设置。
- 构造函数现在接受
net.minecraft.world.level.dimension.DimensionType现在接受一个boolean,表示维度是否可以有末影龙战斗net.minecraft.world.level.dimension.endDragonRespawnAnimation->DragonRespawnStage,不是一对一EndDragonFight->EnderDragonFight,不是一对一
net.minecraft.world.level.gamerules.GameRuleMap现在扩展SavedDataTYPE- 保存数据类型。reset- 将规则重置为其默认值。
net.minecraft.world.level.levelgen.WorldGenSettings现在是一个 final 类而不是记录,扩展SavedDataencode、decode被TYPE取代of- 构造生成设置。
net.minecraft.world.level.saveddataSavedDataType现在接受Identifier而不是字符串作为 idWanderingTraderData- 流浪商人的保存数据。WeatherData- 天气的保存数据。
net.minecraft.world.level.storageDimensionDataStorage->SavedDataStorage,不是一对一LevelData#isThundering、isRaining、setRaining现在在WeatherData中LevelDataAndDimensions现在接受$WorldDataAndGenSettings而不是WorldData$WorldDataAndGenSettings- 保存世界数据和生成设置。
LevelResource现在是一个记录PrimaryLevelData字段已移至各自的保存数据类PLAYER->OLD_PLAYERSINGLEPLAYER_UUID- 一个表示单机世界中玩家 UUID 的字符串。WORLD_GEN_SETTINGS->OLD_WORLD_GEN_SETTINGSwriteLastPlayed- 写入最后玩的玩家。writeVersionTag- 写入数据版本标签。
ServerLevelDatasetThundering、getRainTime、setRainTime、setThunderTime、getThunderTime、getClearWeatherTime、setClearWeatherTime移至WeatherDatagetWanderingTraderSpawnDelay、setWanderingTraderSpawnDelay、getWanderingTraderSpawnChance、setWanderingTraderSpawnChance、getWanderingTraderId、setWanderingTraderId移至WanderingTraderDatagetLegacyWorldBorderSettings、setLegacyWorldBorderSettings被WorldBorder取代getScheduledEvents->MinecraftServer#getScheduledEventsgetGameRules被GameRuleMap取代
WorldDatagetCustomBossEvents、setCustomBossEvents被CustomBossEvents取代createTag不再接受RegistryAccessgetGameRules被GameRuleMap取代getLoadedPlayerTag->getSinglePlayerUUID,不是一对一endDragonFightData、setEndDragonFightData被EnderDragonFight取代worldGenOptions被WorldGenSettings保存数据取代
net.minecraft.world.level.timers.TimerQueue现在扩展SavedData- 构造函数现在接受
$Packed事件,而不是TimerCallbacks和事件数据的Stream store被CODEC、TYPE、codec取代loadEvent、storeEvent被$Event$Packed#codec取代$Event现在是一个记录$Packed- 打包的事件数据。
$Packed- 打包的时间队列。
- 构造函数现在接受
更多渲染变更
材质与动态层选择
方块和物品模型现在不再指定它们属于哪个 RenderType 或 ChunkSectionLayer。相反,这在加载模型时计算,确定每个四边形的关联层。这意味着 ItemBlockRenderTypes 被移除,物品的 RenderType 设置也被完全移除。
为了确定四边形或面被设置到哪个层,会计算纹理的 Transparency。具体来说,对于映射到四边形的 UV 区域,检查是否存在任何透明像素(alpha 为 0)或半透明像素(alpha 不为 0 或 255)。对于 ChunkSectionLayer,如果存在半透明像素则使用 ChunkSectionLayer#TRANSLUCENT,否则如果存在透明像素则使用 CUTOUT,否则使用 SOLID。对于物品 RenderType,如果存在半透明像素则使用 Sheets#translucentItemSheet 和用于方块物品的 translucentBlockItemSheet,否则使用 cutoutItemSheet 和用于方块物品的 cutoutBlockItemSheet。Transparency 也影响 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 重命名为 SpriteId,MaterialSet 重命名为 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 -> CuboidModel,BlockModelWrapper -> CuboidItemModelWrapper)。此外,引用方块状态 JSON 内定义的渲染过程部分已从“block”更改为“block state”(例如,BlockModelPart -> BlockStateModelPart,BlockModelDefinition -> BlockStateModelDispatcher)。您可以认为大多数“block model”类是新的,而那些重命名的类取代了 SpecialBlockModelRenderer 系统。
方块模型系统从所有模型和定义加载并解析后的 ModelManager 开始,准备进行烘焙。方块模型通过 BuiltInBlockModels#crateBlockModels 加载,它将某个 BlockState 链接到 BlockModel$Unbaked。与物品模型类似,未烘焙实例定义了应如何构建方块模型的属性。这些存储在 LoadedBlockModels 中,然后在所有 JSON 之后通过 bake 烘焙成 BlockModel。然后,这个 BlockState 到 BlockModel 的映射存储在 BlockModelSet 中,准备好通过 get 查询,或者更常见的是通过 BlockModelResolver#update 查询,后者调用模型集。任何未延迟定义的模型都会解析为 BlockStateModel 的包装器。
原版为常见用途提供了六种 BlockModel 实现。有 EmptyBlockModel,它不提交任何元素,因此不渲染任何内容;以及 BlockStateModelWrapper,它包装并显示关联的 BlockStateModel。然后,有根据某些属性开关更改模型的等价物(SelectBlockModel)、条件 boolean(ConditionalBlockModel)以及将多个模型组合在一起的组合(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
);
在功能提交过程中,方块模型通过 BlockModelResolver 和 BlockModelRenderState 处理。这类似于其他渲染状态的工作方式。首先,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用于粒子上下文,由下落的灰尘和地形粒子使用
此外,如果使用 BlockState 的 Property 来确定要染色的颜色,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
);
移除旧的方块和物品渲染器
由于 ItemModel 和 BlockModel 现在完全通过它们自己的功能提交管道处理,BlockRenderDispatcher 和 ItemRenderer 已被完全移除,被相应的系统取代。
对象定义变换
ItemModel 和 BlockModel 现在可以接受一个可选的 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 -> extractRenderState,AbstractContainerScreen#renderLabels -> extractLabels,AbstractWidget#renderWidget -> extractWidgetRenderState)。一些缩写也被扩展,要么通过重命名,要么用另一个方法替换(例如,AbstractContainerScreen#renderBg 被 Screen#extractBackground 取代)。
GuiGraphics 也以同样的方式重命名为 GuiGraphicsExtractor。这些方法遵循与 GUI 其余部分类似的模式(例如,hline -> horizontalLine),不同之处在于 draw*、render* 和 submit* 前缀以及 *RenderState 后缀被移除(例如,renderOutline -> outline,submitEntityRenderState -> 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_TEST 被 CompareOp#ALWAYS_PASS 取代。深度信息可以通过 RenderPipeline$Builder#withDepthStencilState 添加到管道中。
可选的 BlendFunction 以及颜色/alpha boolean 现在存储在 ColorTargetState 中。boolean 被合并到一个 int 中,使用低四位作为标志:1 是红色,2 是绿色,4 是蓝色,8 是 alpha。颜色 boolean 使用 7 表示红色、绿色和蓝色;alpha boolean 使用 8;而两者结合使用 15。LopicOp 已被完全移除。颜色信息可以通过 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 后端
CommandEncoder、GpuDevice 和 RenderPassBackend 已拆分为 *Backend 接口,其功能类似于以前的接口,以及包装器类,它持有后端并提供委托调用,执行任何必要的验证。*Backend 接口现在显式执行操作,而不检查操作是否有效。
实体和半透明功能
功能渲染已进一步拆分为两个通道:一个用于实体渲染类型,一个用于半透明渲染类型。因此,大多数 render 方法现在分别具有 renderSolid 和 renderTranslucent 方法。那些只渲染实体或半透明数据的方法只具有其中一个方法。
相机状态
Camera 已更新,类似于其他渲染状态实现,其中相机在 GameRenderer#renderLevel 期间被提取到 CameraRenderState,并传递带有提交和渲染元素所需的数据。
由于此更改,FogRenderer#setupFog 现在返回 FogData,其中包含渲染雾所需的所有信息,而不仅仅是其颜色,并将其存储在 CameraRenderState#fogData 中。
assets/minecraft/shaders/core中的一些着色器现在使用texture而不是texelFetchentity.vshitem.vshrendertype_leash.vshrendertype_text.vshrendertype_text_background.vshrendertype_text_intensity.vsh
assets/minecraft/shaders/coreblock.vsh#minecraft_sample_lightmap->sample_lightmap.glsl#sample_lightmaprendertype_crumbling不再接受texCoord2(光照图)rendertype_entity_alpha、rendertype_entity_decal合并到entity.fsh中,使用DissolveMaskSamplerrendertype_item_entity_translucent_cull->item,不是一对一rendertype_translucent_moving_block已移除- 现在使用
ChunkSectionLayer提供的着色器
- 现在使用
com.mojang.blaze3dGLFWErrorCapture- 在 GL 过程中捕获错误。GLFWErrorScope- 一个定义要捕获的 GL 错误范围的可关闭对象。
com.mojang.blaze3d.openglGlProgram#BUILT_IN_UNIFORMS、INVALID_PROGRAM现在是 finalGlBackend- OpenGL 的 GPU 后端。GlCommandEncoder现在实现CommandEncoderBackend而不是CommandEncoder,该类现在是包私有的getDevice已移除
GlConst#toGl现在接受CompareOp而不是DepthTestFunctionGlDevice现在实现GpuDeviceBackend而不是GpuDevice,该类现在是包私有的- 构造函数现在接受
GpuDebugOptions,其中包含日志级别、是否使用同步日志以及是否使用调试标签,而不是直接传入这些参数
- 构造函数现在接受
GlRenderPass现在实现RenderPassBackend而不是RenderPass,该类现在是包私有的- 构造函数现在接受
GlDevice
- 构造函数现在接受
GlStateManager#_colorMask现在接受int作为颜色掩码,而不是四个boolean
com.mojang.blaze3d.platformClientShutdownWatchdog现在接受Minecraft实例DebugMemoryUntracker#untrack已移除GLX#make(T, Consumer)已移除NativeImagecomputeTransparency- 返回图像中是否至少有一个透明或半透明像素。- 如果图像面积大于 512MiB,或带有颜色数据时大于 2GiB,则会崩溃。
isClosed- 图像是否已关闭或释放。
Transparency- 一个关于某个图像是否具有半透明和/或透明像素的对象。Window现在接受GpuBackend而不是ScreenManagercreateGlfwWindow- 直接使用提供的设置创建 GLFW 窗口。updateDisplay->updateFullscreenIfChanged,不是一对一isResized、resetIsResized- 处理窗口是否已调整大小。backend- 返回GpuBackend。$WindowInitFailed构造函数现在从private变为public
WindowEventHandler#resizeDisplay->resizeGui
com.mojang.blaze3d.pipelineColorTargetState- 一个包含颜色混合函数和掩码的记录。DepthStencilState- 一个包含深度模板数据的记录。RenderPipeline现在接受ColorTargetState而不是可选的BlendFunction、颜色和 alphaboolean以及LogicOp;以及DepthStencilState而不是DepthTestFunction、深度boolean和偏置floatgetDepthTestFunction、isWriteDepth、getDepthBiasScaleFactor、getDepthBiasConstant->getDepthStencilState,不是一对一getColorLogic、getBlendFunction、isWriteColor、isWriteAlpha->getColorTargetState,不是一对一$BuilderwithDepthTestFunction、withDepthWrite、withDepthBias->withDepthStencilState,不是一对一withBlend、withColorWrite、withColorLogic->withColorTargetState,不是一对一
$Snippet现在接受ColorTargetState而不是可选的BlendFunction、颜色和 alphaboolean以及LogicOp;以及DepthStencilState而不是DepthTestFunction和深度boolean
com.mojang.blaze3d.platformBackendOptions- 用于初始化后端的配置。DepthTestFunction->CompareOp,不是一对一NO_DEPTH_TEST->CompareOp#ALWAYS_PASSEQUAL_DEPTH_TEST->CompareOp#EQUALLEQUAL_DEPTH_TEST->CompareOp#LESS_THAN_OR_EQUALLESS_DEPTH_TEST->CompareOp#LESS_THANGREATER_DEPTH_TEST->CompareOp#GREATER_THAN
GLX_initGlfw现在接受BackendOptionsglfwBool-true为1,false为0。
LogicOp枚举已移除
com.mojang.blaze3d.shaders.GpuDebugOptions- GPU 管线的调试选项。com.mojang.blaze3d.systemsBackendCreationException- 当无法创建 GPU 后端时抛出的异常。CommandEncoder->CommandEncoderBackend- 原始接口现在是一个围绕接口的类包装器,在执行验证检查后委托给后端
GpuBackend- 一个负责创建使用的 GPU 设备和显示窗口的接口。GpuDevice->GpuDeviceBackend- 原始接口现在是一个围绕接口的类包装器,在执行验证检查后委托给后端
setVsync- 设置是否启用 VSync。presentFrame- 交换窗口的前后缓冲区以显示当前帧。isZZeroToOne- 是否使用 0 到 1 的 Z 范围而不是 -1 到 1。
RenderPass->RenderPassBackend- 原始接口现在是一个围绕接口的类包装器,在执行验证检查后委托给后端
RenderSystempollEvents现在是公开的flipFrame不再接受WindowinitRenderer现在只接受GpuDevicelimitDisplayFPS->FramerateLimiter#limitDisplayFPSinitBackendSystem现在接受BackendOptions
com.mojang.blaze3d.vertexDefaultVertexFormat#BLOCK不再接受法线向量PoseStack#mulPose、$Pose#mulPose现在有一个接受Transformation的重载QuadInstance- 一个包含四边形颜色、光照坐标和覆盖的类。TlsfAllocator- 一个用于动态内存分配的两级隔离适配分配器。UberGpuBuffer- 一个用于将动态大小的数据上传到 GPU 的缓冲区,用于区块部分层。VertexConsumerputBulkData->putBlockBakedQuad、putBakedQuad;不是一对一- 亮度
float数组、颜色float、光照图int数组和覆盖int被QuadInstance取代 putBlockBakedQuad将PoseStack$Pose替换为 XYZfloat方块位置
- 亮度
addVertex(PoseStack$Pose, Vector3f)->addVertex(PoseStack$Pose, Vector3fc)setNormal(PoseStack$Pose, Vector3f)->setNormal(PoseStack$Pose, Vector3fc)
com.mojang.mathMatrixUtilcheckPropertyRaw现在从private变为publicisOrthonormal已移除
TransformationIDENTITY现在从private变为public- 取代了
identity方法
- 取代了
getTranslation->translationgetLeftRotation->leftRotationgetScale->scalegetRightRotation->rightRotationcompose- 如果存在,将变换应用于给定矩阵。
net.minecraft.SharedConstantsDEBUG_DUMP_INTERPOLATED_TEXTURE_FRAMES已移除DEBUG_PREFER_WAYLAND- 当为 true 时,如果同时支持 Wayland 和 X11,则阻止将平台初始化提示设置为 X11。
net.minecraft.clientCameraBASE_HUD_FOV- 基础 HUD 视场角。setup->update,不是一对一extractRenderState- 提取相机的状态。getFov- 获取视场角。getViewRotationMatrix- 获取投影视图的矩阵。setEntity- 设置相机附加到的实体。getNearPlane现在接受float视场角panoramicForwards- 全景模式下的前向向量。getPartialTickTime已移除setLevel- 设置相机所在的等级。getCameraEntityPartialTicks- 根据实体的状态获取部分刻。
DeltaTracker#advanceTime被advanceGameTime(当boolean为true时)和advanceRealTime取代advanceGameTime、advanceRealTime以前是private,现在是public
FramerateLimiter- 一个用于限制客户端帧率的实用程序。MinecraftnoRender已移除useAmbientOcclusion已移除getBlockRenderer已移除getItemRenderer已移除
OptionsgetCloudsType->getCloudStatusexclusiveFullscreen- 当为true时,全屏模式完全控制显示器。
net.minecraft.client.color.blockBlockColor被BlockTintSource取代,不是一对一getColor->colorInWorld,colorAsTerrainParticle; 不是一对一
BlockColorsgetColor被getTintSources、getTintSource取代;不是一对一register现在接受一个BlockTintSource列表而不是一个BlockColor
BlockTintSource- 一个用于确定如何对BlockState进行单独或上下文着色的源。BlockTintSources- 通用块着色源的实用程序。
net.minecraft.client.data.modelsBlockModelGeneratorscreateSuffixedVariant现在接受一个从Material到TextureMapping的函数用于纹理,而不仅仅是IdentifiercreateAirLikeBlock现在接受一个Material而不是Identifier作为粒子纹理generateSimpleSpecialItemModel现在接受一个可选的TransformationcreateChest现在有一个接受MutiblockChestResources纹理的重载
ItemModelGenerators#generateLayeredItem现在接受Material而不是Identifier作为纹理
net.minecraft.client.data.models.modelItemModelUtilsspecialModel现在有接受Transformation的重载conditional现在有接受Transformation的重载select现在有一个接受Transformation的重载selectBlockItemProperty现在有一个接受Transformation的重载
TexturedModel#createAllSame现在接受一个Material而不是Identifier作为纹理TextureMappingput、putForced现在接受一个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#belowNameDisplaynet.minecraft.client.guiFontdrawInBatch,drawInBatch8xOutline现在接受一个Matrix4fc而不是Matrix4f作为姿态$GlyphVisitor#forMultiBufferSource现在接受一个Matrix4fc而不是Matrix4f作为姿态
Guirender*方法已重命名为extract*render->extractRenderState$RenderFunction接口已移除
GuiGraphics->GuiGraphicsExtractorhLine->horizontalLinevLine->verticalLinerenderOutline->outlinedrawCenteredString->centeredTextdrawString->textdrawStringWithBackdrop->textWithBackdroprenderItem->itemrenderFakeItem->fakeItemrenderItemDecorations->itemDecorationssubmitMapRenderState->mapsubmitEntityRenderState->entitysubmitSkinRenderState->skinsubmitBookModelRenderState->booksubmitBannerPatternRenderState->bannerPatternsubmitSignRenderState->signsubmitProfilerChartRenderState->profilerChartrenderTooltip->tooltiprenderComponentHoverEffect->componentHoverEffect,现在为private而不是public
net.minecraft.client.gui.components- 大多数以
render*或draw*开头的方法已根据用法重命名为extract*或extract*RenderState AbstractWidget#renderWidget->extractWidgetRenderStateDebugScreenOverlay#render3dCrosshair现在接受CameraRenderState而不是Camera,以及 GUI 缩放intLogoRenderer#renderLogo->extractRenderStatePlayerFaceRenderer->PlayerFaceExtractordraw->extractRenderState
Renderable#render->extractRenderStateStringWidget#clipText->ComponentRenderUtils#clipTextTextCursorUtils#draw*->extract*
- 大多数以
net.minecraft.client.gui.components.debugchartAbstractDebugChartdrawChart->extractRenderStatedrawDimensions->extractSampleBarsdrawMainDimension->extractMainSampleBardrawAdditionalDimensions->extractAdditionalSampleBarsrenderAdditionalLinesAndLabels->extractAdditionalLinesAndLabelsdrawStringWithShade->extractStringWithShade
ProfilerPieChart#render->extractRenderState
net.minecraft.client.gui.components.spectator.SpectatorGui#render*->extract*net.minecraft.client.gui.components.toastsNowPlayingToast#renderToast->extractToastToast#render->extractRenderStateToastManager,$ToastInstance#render->extractRenderStateTutorialToast$Icons#render->extractRenderState
net.minecraft.client.gui.contextualbar.ContextualBarRendererrenderBackground->extractBackgroundrender->extractRenderStaterenderExperienceLevel->extractExperienceLevel
net.minecraft.client.gui.fontPlainTextRenderable#renderSprite现在接受一个Matrix4fc而不是Matrix4f作为姿态TextRenderable#render现在接受一个Matrix4fc而不是Matrix4f作为姿态
net.minecraft.client.gui.renderDynamicAtlasAllocator- 一个用于处理动态大小纹理图集的分配器。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.screensLevelLoadingScreen#renderChunks->extractChunksForRenderingScreenrenderWithTooltipAndSubtitles->extractRenderStateWithTooltipAndSubtitlesrenderBackground->extractBackgroundrenderBlurredBackground->extractBlurredBackgroundrenderPanorama->extractPanoramarenderMenuBackground->extractMenuBackgroundrenderMenuBackgroundTexture->extractMenuBackgroundTexturerenderTransparentBackground->extractTransparentBackground
net.minecraft.client.gui.screens.advancementsAdvancementTab#draw*->extract*AdvancementTabTypedraw->extractRenderStatedrawIcon->extractIcon
AdvancementWidgetdraw->extractRenderStatedraw*->extract*
net.minecraft.client.gui.screens.inventory- 大多数以
render*或draw*开头的方法已根据用法重命名为extract*或extract*RenderState AbstractContainerScreenrenderContents->extractContentsrenderCarriedItem->extractCarriedItemrenderSnapbackItem->extractSnapbackItemrenderSlots->extractSlotsrenderTooltip->extractTooltiprenderLabels->extractLabelsrenderBg被Screen#extractBackground取代renderSlot->extractSlot
AbstractMountInventoryScreen#drawSlot->extractSlotAbstractSignEditScreen#renderSignBackground->extractSignBackgroundCyclingSlotBackground#render->extractRenderStateEffectsInInventory#render->extractRenderStateInventoryScreen#renderEntityInInventoryFollowsMouse->extractEntityInInventoryFollowsMouseItemCombinerScreen#renderErrorIcon->extractErrorIcon
- 大多数以
net.minecraft.client.gui.screens.inventory.tooltipClientTooltipComponentrenderText->extractTextrenderImage->extractImage
TooltipRenderUtil#renderTooltipBackground->extractTooltipBackground
net.minecraft.client.gui.screens.optionsDifficultyButtons现在是一个记录,接受LayoutElement、用于难度的CycleButton、LockIconButton和当前Levelcreate现在接受Level并返回DifficultyButtons而不是LayoutElementrefresh- 设置持有的按钮组件的数据。
HasDifficultyReaction- 一个响应难度更改的接口。OptionsScreen现在实现HasDifficultyReactionWorldOptionsScreen现在实现HasDifficultyReaction- 构造函数现在接受
Level
- 构造函数现在接受
net.minecraft.client.gui.screens.recipebookGhostSlotsrender->extractRenderStaterenderTooltip->extractTooltip
RecipeBookComponent#render*->extract*RecipeBookPagerender->extractRenderStaterenderTooltip->extractTooltip
net.minecraft.cilent.gui.screens.reporting.ChatSelectionScreen$ChatSelectionList#renderItem->extractItemnet.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen$GameRuleEntry#renderLabel->extractLabelnet.minecraft.client.gui.spectator.SpectatorMenuItem#renderIcon->extractIconnet.minecraft.client.model.Model#renderType现在有一个返回传入函数的重载net.minecraft.client.model.object.book.BookModel$State不再接受动画位置,并将开放的float移到第一个参数forAnimation- 根据进度获取书本动画的当前状态。
net.minecraft.client.model.object.statue.CopperGolemStatueModel现在使用Unit作为泛型而不是Directionnet.minecraft.client.multiplayer.ClientLevel现在实现BlockAndTintGetterupdate- 更新关卡的光照。
net.minecraft.client.multiplayer.chat.GuiMessageTag$Icon#draw->extractRenderStatenet.minecraft.client.particleParticle#getLightColor->getLightCoordsSimpleVerticalParticle- 一个垂直移动的粒子。SingleQuadParticle$LayerTERRAIN->OPAQUE_TERRAIN,TRANSLUCENT_TERRAINITEMS->OPAQUE_ITEMS,TRANSLUCENT_ITEMSbySprite- 从图集精灵获取层。
net.minecraft.client.rendererCachedOrthoProjectionMatrixBuffer,CachedPerspectiveProjectionMatrixBuffer,PerspectiveProjectionMatrixBuffer->ProjectionMatrixBuffer,有时带有Projection,不是一对一CloudRenderer现在接受云范围intCubeMap不再接受Minecraft实例GameRenderer现在接受ModelManager而不是BlockRenderDispatcherPROJECTION_Z_NEAR->Camera#PROJECTION_Z_NEARsetPanoramicScreenshotParameters,getPanoramicScreenshotParameters->Camera#enablePanoramicMode,disablePanoramicMode; 不是一对一isPanoramicMode->Camera#isPanoramicModegetProjectionMatrix->Camera#getViewRotationProjectionMatrix,不是一对一updateCamera->Camera#update,不是一对一getRenderDistance已移除cubeMap->GuiRenderer#cubeMap,现在为private而不是protectedgetDarkenWorldAmount->getBossOverlayWorldDarkeninglightTexture->lightmap,levelLightmap; 不是一对一getLevelRenderState被getGameRenderState取代,返回GameRenderState而不是LevelRenderStatepick->Minecraft#pick,现在为private而不是publicrender拆分为update、extract和render;boolean现在表示是否推进游戏时间而不是渲染关卡
GlobalSettingsUniform现在接受Vec3相机位置而不是主Camera本身ItemBlockRenderTypes已移除getChunkRenderType、getMovingBlockRenderType现在存储在BakedQuad$SpriteInfo中getRenderLayer(FluidState)->FluidModel#layer,不是一对一setCutoutLeaves已移除- 这应直接从选项中获取
MultiblockChestResources- 一个包含基于ChestType的一些数据的记录。LevelRenderer现在接受GameRenderState而不是LevelRenderStateupdate- 更新关卡。renderLevel现在接受CameraRenderState而不是Camera,一个Matrix4fc而不是Matrix4f用于模型视图,以及ChunkSectionsToRender;不再接受用于投影矩阵的Matrix3fextractLevel- 提取关卡状态。prepareChunkRenders现在是public而不是privatecaptureFrustum,killFrustum,getCapturedFrustum已移除getLightColor->getLightCoords,现在接受BlockAndLightGetter而不是BlockAndTintGetter$BrightnessGetter#packedBrightness现在接受BlockAndLightGetter而不是BlockAndTintGetter
LightTexture->Lightmaptick->LightmapRenderStateExtractor#tickupdateLightTexture->renderpack->LightCoordsUtil#packblock->LightCoordsUtil#blocksky->LightCoordsUtil#skylightCoordsWithEmission->LightCoordsUtil#lightCoordsWithEmission
MaterialMapper->SpriteMapperOrderedSubmitNodeCollectorsubmitBlock已移除submitBlockModel现在接受一个BlockStateModelPart列表而不是BlockStateModel,以及一个int数组(色调颜色数组)而不是三个float用于单一颜色submitItem不再接受RenderTypesubmitModel现在有接受纹理的Identifier或带有SpriteGetter的SpriteId以及一个int色调颜色的重载submitBreakingBlockModel- 提交方块破坏覆盖层。
PanoramaRenderer被Panorama取代registerTextures->GuiRenderer#registerPanoramaTexturesrender->extractRenderState
PanoramicScreenshotParameters记录已移除PostChain现在接受一个Projection和ProjectionMatrixBuffer而不是CachedOrthoProjectionMatrixBufferload现在接受一个Projection和ProjectionMatrixBuffer而不是CachedOrthoProjectionMatrixBuffer
RenderPipelinesENTITY_CUTOUT_NO_CULL->ENTITY_CUTOUT- 原来的带剔除的 cutout 被
ENTITY_CUTOUT_CULL取代
- 原来的带剔除的 cutout 被
ENTITY_CUTOUT_NO_CULL_Z_OFFSET->ENTITY_CUTOUT_Z_OFFSETENTITY_SMOOTH_CUTOUT->END_CRYSTAL_BEAMENTITY_NO_OUTLINE被ENTITY_TRANSLUCENT取代,渲染类型构造时 affects outline 为 falseENTITY_DECAL,DRAGON_EXPLOSION_ALPHA->ENTITY_CUTOUT_DISSOLVE,不是一对一ITEM_ENTITY_TRANSLUCENT_CULL->ENTITY_TRANSLUCENT_CULL,ITEM_CUTOUT,ITEM_TRANSLUCENT; 不是一对一TRANSLUCENT_MOVING_BLOCK被TRANSLUCENT_BLOCK取代BANNER_PATTERN- 用于渲染旗帜图案的管线。
ScreenEffectRenderer#renderScreenEffect现在接受boolean表示玩家是否处于第一人称以及是否隐藏 GUISheets*CHEST_*LOCATION*已根据资源用途合并到CHEST_*字段之一translucentBlockSheet- 使用方块图集的可剔除实体物品半透明渲染类型。cutoutBlockItemSheet- 使用方块图集的物品 cutout 渲染类型。bannerSheet->RenderTypes#entityTranslucent,不是一对一cutoutItemSheet- 使用物品图集的物品 cutout 渲染类型。get*Material->get*SpritechooseMaterial->chooseSprite
SpecialBlockModelRenderer被BuiltInBlockModels取代,不是一对一renderByBlock->BlockModelRenderState#submit*,不是一对一
SubmitNodeCollectiongetBlockSubmits已移除getBreakingBlockModelSubmits- 获取已提交的方块破坏覆盖层。
SubmitNodeCollector$ParticleGroupRendererisEmpty- 此组中是否没有要渲染的粒子。prepare现在接受是否为半透明层准备粒子render不再接受半透明boolean
SubmitNodeStorage$BlockModelSubmit现在接受一个BlockStateModelPart列表而不是BlockStateModel,以及一个int数组(色调颜色数组)而不是三个float用于单一颜色$BlockSubmit已移除$BreakingBlockModelSubmit- 一个包含渲染方块破坏覆盖层信息的记录。$ItemSubmit不再接受RenderType$MovingBlockSubmit,$NameTagSubmit,$ShadowSubmit,$TextSubmit现在接受一个Matrix4fc而不是Matrix4f作为姿态
VirtualScreen被GpuBackend取代
net.minecraft.client.renderer.blockBlockAndTintGetter- 一个用于位置方块着色(例如生物群系)的获取器。BlockModelRenderState- 方块模型的渲染状态。BlockModelResolver- 一个用于设置BlockState渲染状态的辅助类。BlockModelSet- 持有与每个BlockState关联的BlockModel。BlockModelShaper->BlockStateModelSet,不是一对一getParticleIcon->getParticleMaterial,现在返回Material$Baked而不是TextureAtlasSpritegetBlockModel->getgetModelManager,replaceCache已移除
BlockQuadOutput- 一个用于将烘焙四边形信息写入某些输出(如缓冲区)的函数接口。BlockRenderDispatcher类已移除getBlockModelShaper->getModelSet,不是一对一renderBreakingTexture被SubmitNodeCollector#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- 获取用于ChunkSectionLayer的VertexConsumer。
- 构造函数现在接受
ModelBlockRenderer现在接受boolean用于环境光遮蔽和剔除tesselateBlock现在接受一个BlockQuadOutput而不是VertexConsumer,XYZfloat而不是PoseStack,BlockStateModel而不是BlockModelPart列表,不再接受剔除boolean和int覆盖,并接受种子longtesselateWithAO->tesselateAmbientOcclusion,现在是private而不是publictesselateWithoutAO->tesselateFlat,现在是private而不是publicrenderModel现在内联在BlockFeatureRenderer#renderBlockModelSubmits中,一个private方法forceOpaque- 方块纹理是否应为不透明而不是半透明。enableCaching->BlockModelLighter$Cache#enableclearCache->BlockModelLighter$Cache#disable$AdjacencyInfo->BlockModelLighter$AdjacencyInfo,现在是private而不是protected$AmbientOcclusionRenderStorage被BlockModelLighter取代,不是一对一$AmbientVertexRemap->BlockModelLighter$AmbientVertexRemap$Cache->BlockModelLighter$Cache$CommonRenderStorage被BlockModelLighter取代,不是一对一$SizeInfo->BlockModelLighter$SizeInfo
MovingBlockRenderState#level->cardinalLighting,lightEngine; 不是一对一SelectBlockModel- 一个由其解析属性确定或选择的方块模型。
net.minecraft.client.renderer.block.modelBakedQuad->.client.resources.model.geometry.BakedQuad- 构造函数现在接受一个
$MaterialInfo而不是TextureAtlasSprite、int色调索引、int光发射和boolean阴影 FLAG_TRANSLUCENT- 一个标志,标记烘焙四边形具有半透明性。FLAG_ANIMATED- 一个标志,标记烘焙四边形具有动画纹理。isTinted->$MaterialInfo#isTinted$MaterialFlags- 一个注解,标记给定的整数是否定义材质的标志。$MaterialInfo- 一个持有如何渲染四边形信息的记录。
- 构造函数现在接受一个
BlockDisplayContext- 一个表示方块显示上下文的对象。BlockElement->.client.resources.model.cuboid.CuboidModelElementBlockElementFace->.client.resources.model.cuboid.CuboidFaceBlockElementRotation->.client.resources.model.cuboid.CuboidRotationBlockModel- 基础方块模型,用于在世界上下文之外更新渲染状态。- 原始实现已移至
.client.resources.model.cuboid.CuboidModel
- 原始实现已移至
BlockModelDefinition->.block.dispatch.BlockStateModelDispatcherBlockModelPart->.block.dispatch.BlockStateModelPartparticleIcon->particleMaterial,现在返回Material$Baked而不是TextureAtlasSpritematerialFlags- 处理模型使用的材质的标志。
BlockStateModel->.block.dispatch.BlockStateModelparticleIcon->particleMaterial,现在返回Material$Baked而不是TextureAtlasSpritematerialFlags,hasMaterialFlag- 处理模型使用的材质的标志。
BlockStateModelWrapper- 包含模型、色调和变换的基础方块模型。CompositeBlockModel- 将多个方块模型叠加在一起。ConditionalBlockModel- 一个根据从某个属性获取的布尔值显示不同模型的方块模型。EmptyBlockModel- 不显示任何内容的方块模型。FaceBakery->.client.resources.model.cuboid.FaceBakerybakeQuad重载现在接受一个ModelBaker而不是ModelBaker$PartCache,以及一个Material$Baked而不是TextureAtlasSprite- 它还有一个接受
BlockElementFace字段而不是对象本身的重载
- 它还有一个接受
- 另一个
bakedQuad重载现在接受BakedQuad$MaterialInfo而不是int色调索引和光发射,以及阴影boolean
ItemModelGenerator->.client.resources.model.cuboid.ItemModelGeneratorItemTransform->.client.resources.model.cuboid.ItemTransformItemTransforms->.client.resources.model.cuboid.ItemTransformsSimpleModelWrapper->.client.resources.model.SimpleModelWrapper- 构造函数现在接受一个
Material$Baked而不是TextureAtlasSprite作为粒子
- 构造函数现在接受一个
SimpleUnbakedGeometry->.client.resources.model.cuboid.UnbakedCuboidGeometrySingleVariant->.block.dispatch.SingleVariantSpecialBlockModelWrapper- 一个用于通过SpecialModelRenderer提交其元素的方块模型。TextureSlots->.client.resources.model.sprite.TextureSlotsVariant->.block.dispatch.VariantVariantMutator->.block.dispatch.VariantMutatorVariantSelector->.block.dispatch.VariantSelector
net.minecraft.client.renderer.block.model.multipart.*->.block.dispatch.multipart.*net.minecraft.client.renderer.block.model.properties.conditionalConditionalBlockModelProperty- 一个从BlockState计算某个boolean的属性。IsXmas- 返回当前时间是否在 12 月 24 日至 26 日之间。
net.minecraft.client.renderer.block.model.properties.selectDisplayContext- 基于当前BlockDisplayContext的情况。SelectBlockModelProperty- 一个从BlockState计算某个开关状态的属性。
net.minecraft.client.renderer.blockentityAbstractEndPortalRendererrenderCube->submitCube,现在为protected和static而不是privatesubmitSpecial- 提交末地传送门立方体,由特殊渲染器使用。getExtents- 获取每个面的顶点。getOffsetUp,getOffsetDown已移除renderType已移除
AbstractSignRenderer现在接受一个泛型用于SignRenderStategetSignModel现在接受SignRenderState泛型而不是BlockState和WoodTypegetSignModelRenderScale,getSignTextRenderScale,getTextOffset,translateSign被SignRenderState#transformations、SignRenderState$SignTransformations取代getSignMaterial->getSignSprite
BannerRendererTRANSFORMATIONS- 当在墙上或地上时要应用的变换。submitPatterns不再接受基础SpriteId、图案是否有箔以及轮廓颜色submitSpecial现在接受BannerBlock$AttachmentType
BedRenderersubmitSpecial已移除- 这被调用两次
submitPiece或通过BedSpecialRenderer为每个床部件制作组合体所取代
- 这被调用两次
submitPiece现在是public而不是private,接受BedPart而不是Model$Simple、Direction或是否在 Z 方向平移的booleangetExtents现在接受BedPartmodelTransform- 获取给定Direction的变换。
BlockEntityRenderDispatcher现在接受BlockModelResolver而不是BlockRenderDispatcher,并且不再接受ItemRendererprepare现在接受一个Vec3相机位置而不是Camera本身
BlockEntityRendererProvider$Context现在接受BlockModelResolver而不是BlockRenderDispatcher,并且不再接受ItemRenderermaterials->sprites
ChestRendererLAYERS- 持有箱子的模型层。modelTransformation- 获取给定Direction的变换。
ConduitRenderer#DEFAULT_TRANSFORMATION- 要应用的默认变换。CopperGolemStatueBlockRenderer#modelTransformation- 获取给定Direction的变换。DecoratedPotRenderer#modelTransformation- 获取给定Direction的变换。HangingSignRenderer现在使用HangingSignRenderStateMODEL_RENDER_SCALE现在是private而不是publicTRANSFORMATIONS- 当在墙上或地上时要应用的变换。translateBase->baseTransformation,现在是private而不是public$AttachmentType->HangingSignBlock$AttachmentbyBlockState->$Models#get
$ModelKey记录已移除
ShulkerBoxRenderermodelTransform- 获取给定Direction的变换。getExtents不再接受Direction
SignRenderer->StandingSignRendererTRANSFORMATIONS- 当在墙上或地上时要应用的变换。createSignModel现在接受一个PlainSignBlock$Attachment而不是一个表示方块是否站立的boolean
SkullBlockRendererTRANSFORMATIONS- 当在墙上或地上时要应用的变换。submitSkull不再接受Direction或float旋转
WallAndGroundTransformations- 一个持有Direction到墙上变换映射的类,以及一个计算地面变换的int函数,其中int段通常表示旋转状态的数量。
net.minecraft.client.renderer.blockentity.stateBannerRenderStateangle->transformation,不是一对一standing->attachmentType,不是一对一
BedRenderState#isHead->part,不是一对一BlockEntityRenderState#blockState现在是private而不是publicChestRenderState#angle->facing,不是一对一CondiutRenderState->ConduitRenderStateCopperGolemStatueRenderState#oxidationState- 当前的氧化状态。HangingSignRenderState- 悬挂标志的渲染状态。ShelfRenderState#facing- 架子面向的方向。SignRenderState#woodType- 标志的木材类型。SkullblockRenderState#direction,rotationDegrees->transformation,不是一对一StandingSignRenderState- 站立标志的渲染状态。
net.minecraft.client.renderer.chunkChunkSectionLayer现在接受一个boolean表示层是否为半透明,而不是仅在上传时排序byTransparency- 根据其透明度设置获取层。sortOnUpload->translucent,不是一对一vertexFormat- 层使用的管线的顶点格式。
ChunkSectionsToRender#drawsPerLayer->drawGroupsPerLayer,其值为int到绘图列表的映射CompiledSectionMeshuploadMeshLayer被isVertexBufferUploaded、setVertexBufferUploaded取代uploadLayerIndexBuffer被isIndexBufferUploaded、setIndexBufferUploaded取代
RenderRegionCache#createRegion现在接受ClientLevel而不是LevelSectionBuffers->SectionRenderDispatcher$RenderSectionBufferSlice,不是一对一SectionCompiler现在接受boolean用于环境光遮蔽和 cutout 树叶、BlockStateModelSet、FluidStateModelSet和BlockColors而不是BlockRenderDispatcherSectionMeshgetBuffers->getSectionDraw,不是一对一$SectionDraw- 部分的绘图信息。
SectionRenderDispatcher现在接受SectionCompiler而不是BlockRenderDispatcher和BlockEntityRenderDispatchergetRenderSectionSlice- 获取要为块层渲染的部分网格的缓冲区切片。uploadAllPendingUploads->uploadGlobalGeomBuffersToGPU,不是一对一lock,unlock- 处理在将数据从一个位置复制到另一个位置时锁定调度程序,通常用于 GPU 分配。getToUpload已移除setLevel现在接受SectionCompiler$RenderSectionupload,uploadSectionIndexBuffer->addSectionBuffersToUberBuffer,现在是 private$CompileTaskdoTask现在返回一个$SectionTaskResult而不是CompletableFuture
$SectionTaskResult->$RenderSection$CompileTask$SectionTaskResult
net.minecraft.client.renderer.culling.Frustum现在接受一个Matrix4fc而不是Matrix4f用于模型视图set- 从另一个视景体复制信息。
net.minecraft.client.renderer.entityAbstractBoatRenderer现在接受Identifier纹理renderType已移除
AbstractMinecartRendererBLOCK_DISPLAY_CONTEXT- 显示矿车内方块的上下文。submitMinecartContents现在接受一个BlockModelRenderState而不是BlockState
CopperGolemRenderer#BLOCK_DISPLAY_CONTEXT- 显示天线方块的上下文。DisplayRendererBLOCK_DISPLAY_CONTEXT- 显示所显示方块的上下文。blockModelResolver- 方块模型解析器。
EndermanRenderer#BLOCK_DISPLAY_CONTEXT- 显示手持方块的上下文。EntityRenderDispatcher现在接受BlockModelResolver而不是BlockRenderDispatcherEntityRenderer#submitNameTag->submitNameDisplay,现在可选地接受 Y 位置int作为名称标签附件的偏移量EntityRendererProvider$Context现在接受BlockModelResolver而不是BlockRenderDispatchergetMaterials->getSpritesgetBlockRenderDispatcher被getBlockModelResolver取代
IronGolemRenderer#BLOCK_DISPLAY_CONTEXT- 显示手持方块的上下文。ItemFrameRenderer#BLOCK_DISPLAY_CONTEXT- 显示所显示方块的上下文。ItemRenderer类已移除- 使用
ItemStackRenderState将元素提交给功能调度程序 ENCHANTED_GLINT_ARMOR->ItemFeatureRenderer#ENCHANTED_GLINT_ARMORENCHANTED_GLINT_ITEM->ItemFeatureRenderer#ENCHANTED_GLINT_ITEMNO_TINT->ItemFeatureRenderer#NO_TINTgetFoilBuffer->ItemFeatureRenderer#getFoilBuffergetFoilRenderType->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.layersBlockDecorationLayer现在接受一个返回BlockModelRenderState的函数而不是可选的BlockStateMushroomCowMushroomLayer不再接受BlockRenderDispatcherSnowGolemHeadLayer不再接受BlockRenderDispatcher
net.minecraft.client.renderer.entity.stateAvatarRenderState#scoreText->EntityRenderState#scoreTextBlockDisplayEntityRenderState#blockRenderState->blockModel,现在是BlockModelRenderState而不是BlockRenderStateCopperGolemRenderState#blockOnAntenna现在是BlockModelRenderState而不是可选的BlockStateEndermanRenderState#carriedBlock现在是BlockModelRenderState而不是可空的BlockStateIronGolemRenderState#flowerBlock- 铁傀儡手持的花。ItemFrameRenderState#frameModel- 物品框方块的模型。MinecartRenderState#displayBlockState->displayBlockModel,现在是BlockModelRenderState而不是BlockStateMushroomCowRenderState#mushroomModel- 附着在牛上的蘑菇模型。SnowGolemRenderState#hasPumpkin->headBlock,现在是BlockModelRenderState而不是booleanTntRenderState#blockState现在是BlockModelRenderState而不是可空的BlockState
net.minecraft.client.renderer.features- 功能
render方法已拆分为renderSolid(用于不透明渲染类型)和renderTranslucent(用于半透明渲染类型) - 一些
render*方法现在接受OptionsRenderState BlockFeatureRendererrenderSolid现在接受BlockStateModelSet而不是BlockRenderDispatcherrenderTranslucent现在接受BlockStateModelSet和 crumblingMultiBufferSource$BufferSource而不是BlockRenderDispatcher
FeatureRenderDispatcher现在接受GameRenderState和ModelManagerrenderAllFeatures已拆分为renderSolidFeatures和renderTranslucentFeatures- 原始方法现在调用这两个方法,先 solid 后 translucent
clearSubmitNodes- 清除提交节点存储。renderTranslucentParticles- 渲染收集的半透明粒子。
FlameFeatureRenderer#render->renderSolidLeashFeatureRenderer#render->renderSolidNameTagFeatureRenderer#render->renderTranslucentShadowFeatureRenderer#render->renderTranslucentTextFeatureRenderer#render->renderTranslucent
- 功能
net.minecraft.client.renderer.fogFogData#color- 雾的颜色。FogRenderersetupFog现在返回一个FogData而不是Vector4f雾颜色updateBuffer- 用雾数据更新缓冲区。
net.minecraft.client.renderer.gizmos.DrawableGizmoPrimitives#render现在接受一个Matrix4fc而不是Matrix4f用于模型视图net.minecraft.client.renderer.itemBlockModelWrapper->CuboidItemModelWrapper- 构造函数不再接受
RenderType函数,现在接受Matrix4fc变换 $Unbaked现在接受一个可选的Transformation
- 构造函数不再接受
CompositeModel$Unbaked现在接受一个可选的TransformationConiditionalItemModel$Unbaked现在接受一个可选的TransformationItemModel$BakingContextmaterials->spritesmissingItem- 获取带有给定Matrix4fc变换的缺失物品模型。
$Unbaked#bake现在接受来自任何父客户端物品的Matrix4fc变换
ItemStackRenderStatepickParticleIcon->pickParticleMaterial,现在返回Material$Baked而不是TextureAtlasSprite$LayerRenderStateEMPTY_TINTS- 一个表示不应用色调的int数组。setRenderType已移除setParticleIcon->setParticleMaterial,现在接受Material$Baked而不是TextureAtlasSpritesetTransform->setItemTransformsetLocalTransform- 设置客户端物品变换,该变换在物品显示变换后应用。prepareTintLayers->tintLayers,不是一对一
MissingItemModel#withTransform- 获取带有给定变换的缺失物品模型。ModelRenderProperties#particleIcon->particleMaterial,现在接受Material$Baked而不是TextureAtlasSpriteRangeSelectItemModel$Unbaked现在接受一个可选的TransformationSelectItemModel$ModelSelector#get不再支持可空的ItemModel。$Unbaked现在接受一个可选的Transformation$UnbakedSwitch#bake现在接受Matrix4fc变换
SpecialModelWrapper现在接受Matrix4fc变换$Unbaked现在接受一个可选的Transformation
net.minecraft.client.renderer.rendertypeRenderType#outputTarget- 获取输出目标。RenderTypesMOVING_BLOCK_SAMPLER被createMovingBlockSetup取代,现在是privateentityCutoutNoCull->entityCutout- 原来的带剔除的 cutout 被
entityCutoutCull取代
- 原来的带剔除的 cutout 被
entityCutoutNoCullZOffset->entityCutoutZOffsetentitySmoothCutout->endCrystalBeamentityNoOutline->entityTranslucent,affectsOutline为falseentityDecal,dragonExplosionAlpha->entityCutoutDissolve,不是一对一itemEntityTranslucentCull->entityTranslucentCullItemTarget,itemCutout,itemTranslucent; 不是一对一bannerPattern- 用于渲染旗帜图案的渲染类型。
net.minecraft.client.renderer.specialBannerSpecialRenderer,$Unbaked现在接受BannerBlock$AttachmentType$Unbaked现在使用BannerPatternLayers作为泛型
BedSpecialRenderer,$Unbaked现在接受BedPart$Unbaked现在实现NoDataSpecialModelRenderer$Unbaked
BellSpecialRenderer- 钟的特殊渲染器。BookSpecialRenderer- 附魔台上书的特殊渲染器。ChestSpecialRenderer$Unbaked现在实现NoDataSpecialModelRenderer$Unbaked- 构造函数现在接受
ChestType *_CHEST_TEXTURE已从字段名中移除,现在是MultiBlockChestResourcesENDER_CHEST_TEXTURE->ENDER_CHEST
- 构造函数现在接受
ConduitSpecialRenderer$Unbaked现在实现NoDataSpecialModelRenderer$UnbakedCopperGolemStatueSpecialRenderer$Unbaked现在实现NoDataSpecialModelRenderer$UnbakedDecoratedPotSpecialRenderer$Unbaked现在使用PotDecorations作为泛型EndCubeSpecialRenderer- 末地传送门立方体的特殊渲染器。HangingSignSpecialRenderer$Unbaked现在实现NoDataSpecialModelRenderer$Unbaked- 构造函数现在接受
HangingSignBlock$Attachment
- 构造函数现在接受
NoDataSpecialModelRenderersubmit不再接受ItemDisplayContext$Unbaked- 不需要提取数据的特殊模型渲染器的未烘焙渲染器。
PlayerHeadSpecialRenderer$Unbaked现在使用PlayerSkinRenderCache$RenderInfo作为泛型ShieldSpecialRendererDEFAULT_TRANSFORMATION- 要应用的默认变换。$Unbaked现在使用DataComponentMap作为泛型
ShulkerBoxSpecialRenderer,$Unbaked不再接受Direction方向$Unbaked现在实现NoDataSpecialModelRenderer$Unbaked
SkullSpecialRenderer$Unbaked现在实现NoDataSpecialModelRenderer$UnbakedSpecialModelRenderersubmit不再接受ItemDisplayContext$BakingContextmaterials->sprites$Simple被BlockModel$BakingContext、ItemModel$BakingContext取代materials->sprites
$Unbaked现在具有从表示对象中提取参数的泛型
SpecialModelRenderers#createBlockRenderers->BuiltInBlockModels#createBlockModels,不是一对一StandingSignSpecialRenderer$Unbaked现在实现NoDataSpecialModelRenderer$Unbaked- 构造函数现在接受
PlainSignBlock$Attachment
- 构造函数现在接受
TridentSpecialRendererDEFAULT_TRANSFORMATION- 要应用的默认变换。$Unbaked现在实现NoDataSpecialModelRenderer$Unbaked
net.minecraft.client.renderer.state.*->.state.level.*net.minecraft.client.renderer.stateGameRenderState- 游戏的渲染状态。OptionsRenderState- 客户端用户选项的渲染状态。WindowRenderState- 游戏窗口的渲染状态。
net.minecraft.client.renderer.state.gui.GuiRenderState#submit*方法已重命名为add*net.minecraft.client.renderer.state.levelBlockBreakingRenderState现在是一个记录,不再扩展MovingBlockRenderState- 构造函数接受
BlockPos、BlockState和当前进度int
- 构造函数接受
CameraEntityRenderState- 相机实体的渲染状态。CameraRenderStatexRot,yRot- 相机的旋转。entityPos已移除isPanoramicMode- 相机是否处于全景模式。cullFrustum- 剔除视景体。fogType,fogData- 雾元数据。hudFov- HUD 视场角。depthFar- 深度 Z 远平面。projectionMatrix,viewRotationMatrix- 用于从世界空间转换到屏幕空间的矩阵。entityRenderState- 相机附加到的实体。
LevelRenderStatelastEntityRenderStateCount- 渲染到屏幕的实体数量。cloudColor,cloudHeight- 云元数据。
LightmapRenderState- 光照图的渲染状态。
net.minecraft.client.renderer.textureMipmapGenerator#generateMipLevels现在接受计算出的图像TransparencySpriteContentstransparency- 获取精灵的透明度。getUniqueFrames现在返回一个IntList而不是IntStreamcomputeTransparency- 计算选定 UV 边界的透明度。$AnimatedTexture#getUniqueFrames现在返回一个IntList而不是IntStream
TextureAtlasSprite#transparency- 获取精灵的透明度。
net.minecraft.client.resources.modelAtlasManager->.model.sprite.AtlasManagerBlockModelRotation->.client.renderer.block.dispatch.BlockModelRotationMaterial->.model.sprite.SpriteId,不是一对一MaterialSet->.model.sprite.SpriteGetterMissingBlockModel->.model.cuboid.MissingCuboidModelModelBakersprites->materialsparts->interner$PartCache->$Internervector(float, float, float)已移除materialInfo- 获取内部化的材质信息对象。
ModelBakeryBANNER_BASE->Sheets#BANNER_BASESHIELD_BASE->Sheets#SHIELD_BASENO_PATTERN_SHIELD->Sheets#SHIELD_BASE_NO_PATTERNLAVA_*->FluidStateModelSet#LAVA_MODEL,现在是private而不是publicWATER_*->FluidStateModelSet#WATER_MODEL,现在是private而不是public$BakingResult#getBlockStateModel- 从BlockState获取BlockStateModel。$MissingModels现在接受一个MissingItemModel而不是ItemModel用于Item,以及一个FluidModel
ModelManagerBLOCK_OR_ITEM已移除getMissingBlockStateModel->BlockStateModelSet#missingModelgetBlockModelShaper->getBlockStateModelSet,不是一对一getBlockModelSet- 获取BlockState到方块模型的映射。specialBlockModelRenderer已移除getFluidStateModelSet- 获取Fluid到流体模型的映射。
ModelState->.client.renderer.block.dispatch.ModelStateQuadCollection->.model.geometry.QuadCollectionaddAll- 添加另一个四边形集合中的所有元素。materialFlags,hasMaterialFlag- 处理模型使用的材质的标志。
ResolvedModel#resolveParticleSprite->resolveParticleMaterial,现在返回Material$Baked而不是TextureAtlasSpriteSpriteGetter->.model.sprite.MaterialBakerUnbakedGeometry->.model.geometry.UnbakedGeometryWeightedVariants->.client.renderer.block.dispatch.WeightedVariants
net.minecraft.client.resources.model.sprite.Material- 对纹理精灵的引用,以及是否强制纹理半透明。net.minecraft.world.entity.animal.Animal#isBrightEnoughToSpawn现在接受一个BlockAndLightGetter而不是BlockAndTintGetternet.minecraft.world.levelBlockAndTintGetter->BlockAndLightGetterBlockAndTintGetter现在是客户端专用的,实现BlockAndLightGettergetShade->cardinalLighting;不是一对一getBlockTint->BlockAndTintGetter#getBlockTint
CardinalLighting- 持有每个方向应用的光照。EmptyBlockAndTintGetter->BlockAndTintGetter#EMPTYLevelReader现在实现BlockAndLightGetter而不是BlockAndTintGetter
net.minecraft.world.level.blockBannerBlock$AttachmentType- 旗帜附着到另一个方块的位置。CeilingHangingSignBlock现在实现HangingSignBlockgetAttachmentPoint- 获取标志附着到另一个方块的位置。
HangingSignBlock- 一个定义附着到另一个方块的悬挂标志的接口。PlainSignBlock- 一个定义附着到另一个方块的普通标志的接口。StandingSignBlock现在实现PlainSignBlockWallingHangingSignBlock现在实现HangingSignBlockWallSignBlock现在实现PlainSignBlock
net.minecraft.world.level.block.state.BlockBehaviour#getLightBlock,$BlockStateBase#getLightBlock->getLightDampeningnet.minecraft.world.level.block.state.propertiesBedPart#CODEC- 床部分的编解码器。ChestType#CODEC- 箱子类型的编解码器。
net.minecraft.world.level.dimension.DimensionType$CardinalLightType->CardinalLighting$Type
次要迁移
以下是有用或有趣的添加、更改和删除列表,这些内容在入门指南中不值得单独列出一个章节。
可种植标签
用于确定可种植植物能否存活或被放置的方块已移至方块和流体标签。每个此类标签以 support_* 开头,后跟方块(例如 bamboo、cactus)或组(例如 crops、dry_vegetation)。这由相关的方块子类通过重写 Block#canSurvive 或对于植被 VegetationBlock#mayPlaceOn 来处理。
net.minecraft.world.level.blockAttachedStemBlock现在接受一个TagKey表示它可以放置在上面的方块FarmBlock->FarmlandBlockFungusBlock->NetherFungusBlock,不是一对一RootsBlock->NetherRootsBlock,不是一对一WaterlilyBlock->LilyPadBlock,不是一对一StemBlock现在接受一个TagKey表示它可以放置在上面的方块,以及一个TagKey表示其果实可以放置在上面的方块
容器屏幕变更
AbstractContainerScreen 的使用略有变化,需要一些小的更改。首先,imageWidth 和 imageHeight 现在是 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而不是ClickTyperender重写现在默认调用renderTooltip
net.minecraft.world.inventoryAbstractContainerMenu#clicked现在接受一个ContainerInput而不是ClickTypeClickType->ContainerInput
新标签提供者
添加了一个新的 TagsProvider,它提供了一个处理 Holder$Reference 的工具,称为 HolderTagProvider。这仅由 PotionTagsProvider 使用。
此外,TagBuilder 现在提供了一种设置标签上 replace 字段的方法,该方法在反序列化期间删除所有先前读取的条目。
net.minecraft.data.tagsFeatureTagsProvider- 用于ConfiguredFeature的标签提供器。HolderTagProvider- 一个带有通过其引用持有者附加标签的工具的标签提供器。KeyTagProvider#tag现在有一个重载,指示是否替换标签中的条目。PotionTagsProvider- 用于药水标签的提供器。TradeRebalanceTradeTagsProvider- 用于交易重新平衡的村民交易标签提供器。VillagerTradesTagsProvider- 用于村民交易标签的提供器。
net.minecraft.tagsFeatureTags- 用于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 是一个附加到某些对象的接口,这些对象表示某个其他“类型”对象的实例。例如,Entity 是 EntityType 的类型化实例,或者 BlockState 是 Block 的类型化实例。此接口旨在作为一种标准方法,提供对类型 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.entityEntity现在实现TypedInstance<EntityType<?>>EntityType#is->TypedInstance#is- 现在在
Entity实例上
- 现在在
net.minecraft.world.item.ItemStack现在实现TypedInstance<Item>getItemHolder->typeHoldergetTags->tags
net.minecraft.world.level.block.entityBlockEntity现在实现TypedInstance<BlockEntityType>BlockEntityType#getKey已移除
net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase现在实现TypedInstance<Block>getBlockHolder->typeHoldergetTags->tags
net.minecraft.world.level.material.FluidState现在实现TypedInstance<Fluid>holder->typeHoldergetTags->tags
实体纹理与成年幼年模型
assets/minecraft/textures/entity/* 中的实体纹理现已分类到子目录中(例如,熊猫纹理的 entity/panda,或猪纹理的 entity/pig)。大多数纹理已以实体类型开头后跟下划线及其变体命名(例如,喷溅箭的 arrow_tipped,冷猪变体的 pig_cold,或棕色熊猫变体的 panda_brown)。
此外,一些动物模型已拆分为幼年和成年变体的单独类。这些模型要么直接扩展抽象模型实现(例如 AbstractFelineModel),要么扩展原始模型类(例如 PigModel)。
net.minecraft.client.animation.definitionsBabyArmadilloAnimation- 幼年犰狳的动画。BabyAxolotlAnimation- 幼年美西螈的动画。BabyRabbitAnimation- 幼年兔子的动画。CamelBabyAnimation- 幼年骆驼的动画。FoxBabyAnimation- 幼年狐狸的动画。RabbitAnimation- 兔子的动画。
net.minecraft.client.modelHumanoidModelADULT_ARMOR_PARTS_PER_SLOT,BABY_ARMOR_PARTS_PER_SLOT- 装备槽位到模型部件键的映射。createBabyArmorMeshSet- 为幼年类人生物创建盔甲模型集。createArmorMeshSet现在可以接受一个装备槽位到要保留的模型部件键的映射setAllVisible已移除
QuadrupedModel现在有一个接受RenderType函数的构造函数
net.minecraft.client.model.animal.armadilloAdultArmadilloModel- 成年犰狳的实体模型。ArmadilloModel现在是抽象的- 构造函数现在接受行走、卷起/展开和窥视动画的定义
BABY_TRANSFORMER已直接合并到BabyArmadilloModel的层定义中HEAD_CUBE,RIGHT_EAR_CUBE,LEFT_EAR_CUBE现在是protected而不是privatecreateBodyLayer->AdultArmadilloModel#createBodyLayer,BabyArmadilloModel#createBodyLayer
BabyArmadilloModel- 幼年犰狳的实体模型。
net.minecraft.client.model.animal.axolotl.AxolotlModel->AdultAxolotlModel,BabyAxolotlModelnet.minecraft.client.model.animal.beeAdultBeeModel- 成年蜜蜂的实体模型。BabyBeeModel- 幼年蜜蜂的实体模型。BeeModel现在是抽象的BABY_TRANSFORMER已直接合并到BabyBeeModel的层定义中BONE,STINGER,FRONT_LEGS,MIDDLE_LEGS,BACK_LEGS现在是protected而不是privatebone现在是protected而不是privatecreateBodyLayer->AdultBeeModel#createBodyLayer,BabyBeeModel#createBodyLayerbobUpAndDown- 以期望的速度上下摆动蜜蜂,取决于其当前年龄。
net.minecraft.client.model.animal.camelAdultCamelModel- 成年骆驼的实体模型。BabyCamelModel- 幼年骆驼的实体模型。CamelModel现在是抽象的- 构造函数现在接受行走、坐下(带/不带姿势)、站立、闲置和冲刺动画的定义
BABY_TRANSFORMER已直接合并到BabyCamelModel的层定义中createBodyLayer->AdultCamelModel#createBodyLayer,BabyCamelModel#createBodyLayer
CameSaddleModel现在扩展AdultCamelModel而不是CamelModel
net.minecraft.client.model.animal.chickenAdultChickenModel- 成年鸡的实体模型。BabyChickenModel- 幼年鸡的实体模型。ChickenModel现在是抽象的RED_THING->AdultChickenModel#RED_THINGBABY_TRANSFORMER已直接合并到BabyChickenModel的层定义中createBodyLayer->AdultChickenModel#createBodyLayercreateBaseChickenModel->AdultChickenModel#createBaseChickenModel
ColdChickenModel现在扩展AdultChickenModel
net.minecraft.client.model.animal.cow.BabyCowModel- 幼年牛的实体模型。net.minecraft.client.model.animal.dolphin.BabyDolphinModel- 幼年海豚的实体模型。net.minecraft.client.model.animal.equineAbstractEquineModel现在有一个直接指定要使用的ModelPart的重载BABY_TRANSFORMER已直接合并到BabyDonkeyModel的层定义中rightHindLeg,leftHindLeg,rightFrontLeg,leftFrontLeg现在是protected而不是privatecreateBabyMesh->BabyHorseModel#createBabyMesh,不是一对一offsetLegPositionWhenStanding- 当实体站立时偏移腿的位置。getLegStandAngle,getLegStandingYOffset,getLegStandingZOffset,getLegStandingXRotOffset,getTailXRotOffset- 马模型各部分的偏移和角度。animateHeadPartsPlacement- 根据其进食和站立状态动画头部。
BabyDonkeyModel- 幼年驴的实体模型。BabyHorseModel- 幼年马的实体模型。DonkeyModel现在有一个直接指定要使用的ModelPart的重载createBabyLayer->BabyDonkeyModel#createBabyLayer
EquineSaddleModel#createFullScaleSaddleLayer已移除 合并到createSaddleLayer中,移除了幼年变体
net.minecraft.client.model.animal.felineCatModel->AdultCatModel,BabyCatModel; 不是一对一FelineModel->AbstractFelineModel,不是一对一- 实现为
AdultFelineModel和BabyFelineModel
- 实现为
OcelotModel->AdultOcelotModel,BabyOcelotModel; 不是一对一
net.minecraft.client.model.animal.foxAdultFoxModel- 成年狐狸的实体模型。BabyFoxModel- 幼年狐狸的实体模型。FoxModel现在是抽象的BABY_TRANSFORMER已直接合并到BabyFoxModel的层定义中body,rightHindLeg,leftHindLeg,rightFontLeg,leftFrontLeg,tail现在是protected而不是privatecreateBodyLayer->AdultFoxModel#createBodyLayer,BabyFoxModel#createBodyLayerset*Pose- 设置狐狸当前姿势的方法。
net.minecraft.client.model.animal.goatBabyGoatModel- 幼年山羊的实体模型。GoatModel#BABY_TRANSFORMER已直接合并到BabyGoatModel的层定义中
net.minecraft.client.model.animal.llamaBabyLlamaModel- 幼年羊驼的实体模型。LlamaModel#createBodyLayer不再接受表示实体是否为幼年的boolean
net.minecraft.client.model.animal.pandaBabyPandaModel- 幼年熊猫的实体模型。PandaModelBABY_TRANSFORMER已直接合并到BabyPandaModel的层定义中animateSitting- 动画熊猫坐下。
net.minecraft.client.model.animal.pig.BabyPigModel- 幼年猪的实体模型。net.minecraft.client.model.animal.polarbearBabyPolarBearModel- 幼年北极熊的实体模型。PolarBearModel#BABY_TRANSFORMER已直接合并到BabyPolarBearModel的层定义中
net.minecraft.client.model.animal.rabbitAdultRabbitModel- 成年兔子的实体模型。BabyRabbitModel- 幼年兔子的实体模型。RabbitModel现在是抽象的- 构造函数现在接受跳跃和空闲头部倾斜的两个动画定义
FRONT_LEGS,BACK_LEGS- 实体腿的子名称。LEFT_HAUNCH,RIGHT_HAUNCH现在是protectedcreateBodyLayer->AdultRabbitModel#createBodyLayer,BabyRabbitModel#createBodyLayer; 不是一对一
net.minecraft.client.model.animal.sheepBabySheepModel- 幼年羊的实体模型。SheepModel#BABY_TRANSFORMER已直接合并到BabySheepModel的层定义中
net.minecraft.client.model.animal.snifferSnifferModel#BABY_TRANSFORMER已直接合并到SniffletModel的层定义中SniffletModel- 幼年嗅探兽的实体模型。
net.minecraft.client.model.animal.squidBabySquidModel- 幼年鱿鱼的实体模型。SquidModel#createTentacleName现在是 protected 而不是 private
net.minecraft.client.model.animal.turtleAdultTurtleModel- 成年海龟的实体模型。BabyTurtleModel- 幼年海龟的实体模型。TurtleModel现在是抽象的- 构造函数现在可以接受渲染类型函数
BABY_TRANSFORMER已直接合并到BabyTurtleModel的层定义中createBodyLayer->AdultTurtleModel#createBodyLayer,BabyTurtleModel#createBodyLayer
net.minecraft.client.model.animal.wolfAdultWolfModel- 成年狼的实体模型。BabyWolfModel- 幼年狼的实体模型。WolfModel现在是抽象的ModelPart字段现在都是 protectedcreateMeshDefinition->AdultWolfModel#createBodyLayer,BabyWolfModel#createBodyLayer; 不是一对一shakeOffWater- 甩水时设置身体旋转。setSittingPose- 设置狼的坐姿。
net.minecraft.client.model.geomModelLayersCOLD_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.hoglinBabyHoglinModel- 幼年疣猪兽的实体模型。HoglinModelBABY_TRANSFORMER已直接合并到BabyHoglinModel的层定义中head现在是protected而不是privatecreateBabyLayer->BabyHoglinModel#createBodyLayer
net.minecraft.client.model.monster.piglinAbstractPiglinModel现在是抽象的leftSleeve,rightSleeve,leftPants,rightPants,jacket已移除ADULT_EAR_ANGLE_IN_DEGREES,BABY_EAR_ANGLE_IN_DEGREES- 猪灵耳朵的角度。createMesh被AdultPiglinModel#createBodyLayer,AdultZombifiedPiglinModel#createBodyLayer,BabyPiglinModel#createBodyLayer,BabyZombifiedPiglinModel#createBodyLayer取代createBabyArmorMeshSet- 为幼年猪灵模型创建盔甲网格。getDefaultEarAngleInDegrees- 获取默认耳朵角度。
AdultPiglinModel- 成年猪灵的实体模型。AdultZombifiedPiglinModel- 成年僵尸猪灵的实体模型。BabyPiglinModel- 幼年猪灵的实体模型。BabyZombifiedPiglinModel- 幼年僵尸猪灵的实体模型。PiglinModel现在是抽象的ZombifiedPiglinModel现在是抽象的
net.minecraft.client.model.monster.striderAdultStriderModel- 成年炽足兽的实体模型。BabyStriderModel- 幼年炽足兽的实体模型。StriderModel现在是抽象的BABY_TRANSFORMER已直接合并到BabyStriderModel的层定义中rightLeg,leftLeg,body现在是protected而不是privateSPEED- 移动动画的速度标量。customAnimations- 额外的动画设置。animateBristle- 动画炽足兽的鬃毛。
net.minecraft.client.model.monster.zombieBabyDrownedModel- 幼年溺尸的实体模型。BabyZombieModel- 幼年僵尸的实体模型。BabyZombieVillagerModel- 幼年僵尸村民的实体模型。
net.minecraft.client.model.npcBabyVillagerModel- 幼年村民的实体模型。VillagerModel#BABY_TRANSFORMER已直接合并到BabyVillagerModel的层定义中
net.minecraft.client.renderer.entityAxolotlRenderer现在接受一个EntityModel<AxolotlRenderState>作为其泛型CamelHuskRenderer现在扩展MobRenderer而不是CamelRendererCamelRenderer#createCamelSaddleLayer现在是staticCatRenderer现在接受一个AbstractFelineModel作为其泛型DonkeyRenderer现在接受一个EquipmentClientInfo$LayerType和ModelLayerLocation用于鞍层和模型,并将DonkeyRenderer$Type拆分为成年类型和幼年类型$TypeDONKEY_BABY- 驴的幼年变体。MULE_BABY- 骡的幼年变体。
OcelotRenderer现在接受一个AbstractFelineModel作为其泛型UndeadHorseRenderer现在接受一个EquipmentClientInfo$LayerType和ModelLayerLocation用于鞍层和模型,并将UndeadHorseRenderer$Type拆分为成年类型和幼年类型$TypeSKELETON_BABY- 骷髅马的幼年变体。ZOMBIE_BABY- 僵尸马的幼年变体。
net.minecraft.client.renderer.entity.layers.CatCollarLayer现在接受一个AbstractFelineModel作为其泛型net.minecraft.client.renderer.entity.stateAxolotlRenderStateswimAnimation- 游泳的状态。walkAnimationState- 在地面(非水下)行走的状态。walkUnderWaterAnimationState- 在水下行走的状态。idleUnderWaterAnimationState- 在水下但未在地面闲置的状态。idleUnderWaterOnGroundAnimationState- 在水下接触海底时闲置的状态。idleOnGroundAnimationState- 在地面(非水下)闲置的状态。playDeadAnimationState- 装死的状态。
RabbitRenderStatehopAnimationState- 实体正在执行的跳跃状态。idleHeadTiltAnimationState- 执行空闲动画时头部倾斜的状态。
net.minecraft.client.resources.model.EquipmentClientInfo$LayerType#HUMANOID_BABY- 幼年类人生物装备层。net.minecraft.sounds.SoundEvents#PIG_EAT_BABY- 幼年猪进食时播放的声音。net.minecraft.world.entity.AgeableMobcanUseGoldenDandelion- 是否可以使用金蒲公英来锁定实体的年龄。setAgeLocked- 将实体设置为年龄锁定。makeAgeLockedParticle- 在锁定实体年龄时创建粒子。AGE_LOCK_DOWNWARDS_MOVING_PARTICLE_Y_OFFSET- 粒子起始位置的 Y 偏移量。
net.minecraft.world.entity.animal.axolotl.AxolotlswimAnimation- 游泳的状态。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.TadpoleageLockParticleTimer- 年龄锁定实体的粒子应生成的计时器。setAgeLocked,isAgeLocked- 处理蝌蚪的年龄锁定。
net.minecraft.world.entity.animal.goat.GoatBABY_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.RabbithopAnimationState- 实体正在执行的跳跃状态。idleHeadTiltAnimationState- 执行空闲动画时头部倾斜的状态。
net.minecraft.world.entity.animal.wolfWolfSoundVariant->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.MultiPlayerGameModeinteract现在接受EntityHitResultinteractAt已移除
net.minecraft.world.entity.Entityinteract现在接受一个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)->containingChunkPos(long)->unpacktoLong,asLong->pack
不再有绊线管线
绊线渲染管线已被完全移除。现在,绊线使用带有 alpha_cutoff_bias 为 0.1 的 cutout 用于纹理。
net.minecraft.client.renderer.RenderPipelines#TRIPWIRE_BLOCK,TRIPWIRE_TERRAIN已移除net.minecraft.client.renderer.chunkChunkSectionLayer#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.LivingEntitybrainProvider已移除makeBrain现在接受一个Brain$Packed而不是Dynamic
net.minecraft.world.entity.aiActivityData- 一个记录,包含正在执行的活动、该活动中要执行的行为、任何记忆条件以及停止后要擦除的记忆。Brain现在是 protected 的,接受一个ActivityData列表、一个MemoryMap而不是不可变的记忆列表、一个RandomSource,并且不提供Codec- 公共构造函数不再接受任何参数
provider现在有一个只接受传感器类型的重载,默认记忆类型为空列表- 一些
provider方法也接受要执行的Brain$ActivitySupplier
- 一些
codec,serializeStart被pack,Brain$Packed取代addActivityAndRemoveMemoryWhenStopped,addActivityWithConditions合并到addActivity中- 或者使用
ActivityData#create
- 或者使用
copyWithoutBehaviors已移除getMemories被forEach取代$ActivitySupplier- 为实体创建活动列表。$MemoryValue已移除$Packed- 一个包含序列化大脑到磁盘的数据的记录。$Provider#makeBrain现在接受实体和要反序列化记忆的Brain$Packed$Visitor- 访问大脑内的记忆,无论是已定义但为空、存在还是带有计时器存在。
net.minecraft.world.entity.ai.behavior.VillagerGoalPackages#get*Package不再接受VillagerProfessionnet.minecraft.world.entity.ai.memoryExpirableValue->MemorySlot,不是一对一- 原始的
ExpirableValue现在是一个记录,定义记忆何时过期,而不是自己更新
- 原始的
MemoryMap- 将记忆类型链接到其存储值的映射。MemoryModuleType- 记忆是否可以序列化。
net.minecraf.tworld.entity.ai.sensing.Sensor#randomlyDelayStart- 延迟传感器多长时间。net.minecraft.world.entity.animal.allay.AllayAiSENSOR_TYPES,MEMORY_TYPES->BRAIN_PROVIDER,现在是 private;不是一对一makeBrain->getActivities,不是一对一
net.minecraft.world.entity.animal.armadillo.ArmadilloAi#makeBrain,brainProvider->getActivities,现在是protected,不是一对一net.minecraft.world.entity.animal.axolotlAxolotlSENSOR_TYPES->BRAIN_PROVIDER,现在是 private;不是一对一AxolotlAimakeBrain->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.frogFrog#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.goatGoat#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.nautilusNautilusAiSENSOR_TYPES,MEMORY_TYPES->Nautilus#BRAIN_PROVIDER,现在是 private,不是一对一makeBrain,brainProvider->getActivities,现在是public,不是一对一
ZombieNautilusAiSENSOR_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.ZoglinSENSOR_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.hoglinHoglin#SENSOR_TYPES->BRAIN_PROVIDER,现在是 private;不是一对一HoglinAi#makeBrain->getActivities,不是一对一
net.minecraft.world.entity.monster.piglinPiglin#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 构建,使用 addSchema 和 addFixer 为所需版本应用修复器。在升级过程中,文件在临时文件夹中创建,然后移动到世界文件夹。原始世界文件夹在删除之前被移动到另一个文件夹。
net.minecraft.client.gui.screens.FileFixerAbortedScreen- 当文件修复被中止时显示的屏幕。net.minecraft.client.gui.screens.worldselection.FileFixerProgressScreen- 尝试显示升级和修复世界文件的进度时显示的屏幕。net.minecraft.server.packs.linkfsDummyFileAttributes->.minecraft.util.DummyFileAttributesLinkFSPathDIRECTORY_ATTRIBUTES->DummyFileAttributes#DIRECTORYFILE_ATTRIBUTES->DummyFileAttributes#FILE
net.minecraft.utilExtraCodecspathCodec- 路径的编解码器,从字符串转换并使用 Unix 分隔符存储。relaiveNormalizedSubPathCodec- 路径的编解码器,已标准化并验证以确保其是相对的。guardedPathCodec- 路径的编解码器,从某个基础路径解析和相对化。
FileUtilisPathNormalized,createPathToResource已移除isEmptyPath- 返回路径是否为空。
Util#safeMoveFile- 使用给定选项安全地将文件从某个源移动到目标。
net.minecraft.util.filefixAbortedFileFixException- 当文件修复已中止且无法还原移动时抛出的异常。AtmoicMoveNotSupportedFileFixException- 当用户文件系统不支持原子移动时抛出的异常。CanceledFileFixException- 当文件修复升级过程被取消时抛出的异常。FailedCleanupFileFixException- 当文件修复无法移动或删除文件夹进行清理时抛出的异常。FileFix- 对文件执行某些操作的修复器。FileFixerUpper- 要执行操作的文件修复器。FileFixException- 尝试通过文件修复器升级世界时抛出的异常。FileFixUtil- 执行某些文件操作的工具。FileSystemCapabilities- 目录中文件系统的能力。
net.minecraft.util.filefix.accessChunkNbt- 处理升级区块 nbt。CompressedNbt- 处理升级压缩的 nbt 文件。FileAccess- 提供对某些文件资源的引用,给定其关系。FileAccessProvider- 文件访问的提供器,给定与源的关系。FileRelation- 文件与某个源路径的关系的定义。FileResourceType- 定义要访问的资源类型。FileResourceTypes- 所有定义的文件资源类型。LevelDat- 处理升级 level dat。PlayerData- 处理升级玩家数据。SavedDataNbt- 处理升级保存的数据。
net.minecraft.util.filefix.fixes.*- 要应用到文件的原版修复。net.minecraft.util.filefix.operationsApplyInFolders- 在相关文件夹内应用给定操作。DeleteFileOrEmptyDirectory- 删除目标文件或空目录。FileFixOperation- 在某个基础目录内执行的操作。FileFixOperations- 所有原版文件修复操作。GroupMove- 移动某个目录,对其内容应用任何移动操作。ModifyContent- 修改文件的内容。Move- 将文件从某个源移动到某个目标。RegexMove- 移动所有匹配给定源模式的文件到目标,替换匹配的部分。
net.minecraft.util.filefix.virtualfilesystemCopyOnWriteFileStore- 使用写时复制原理的文件存储。CopyOnWriteFileSystem- 使用写时复制原理的文件系统。CopyOnWriteFSPath- 使用写时复制原理的路径。CopyOnWriteFSProvider- 使用写时复制原理的文件系统提供器。DirectoryNode- 某个写时复制文件系统路径的目录节点。FileMove- 一个记录,包含文件被移动到的路径。FileNode- 某个写时复制文件系统路径的文件节点。Node- 某个写时复制文件系统路径的节点。
net.minecraft.util.filefix.virtualfilesystem.exceptionCowFSCreationException- 当无法创建文件系统时的CowFSFileSystemException。CowFSDirectoryNotEmptyException- 专门针对写时复制系统的DirectoryNotEmptyException。CowFSFileAlreadyExistsException- 专门针对写时复制系统的FileAlreadyExistsException。CowFSFileSystemException- 专门针对写时复制系统的FileSystemException。CowFSIllegalArgumentException- 尝试在写时复制系统上操作时的IllegalArgumentException。CowFSNoSuchFileException- 专门针对写时复制系统的NoSuchFileException。CowFSNotDirectoryException- 专门针对写时复制系统的NotDirectoryException。CowFSSymlinkException- 尝试将写时复制系统与符号链接一起使用时的CowFSCreationException。
net.minecraft.util.worldupdateUpgradeProgressgetTotalFiles->getTotalFileFixState,不是一对一addTotalFiles->addTotalFileFixOperations,不是一对一getTypeFileFixStats,getRunningFileFixerStats- 获取特定文件组的修复器统计信息。incrementFinishedOperations,incrementFinishedOperationsBy- 增加已完成操作的数量。setType,getType- 获取升级进度的类型。setApplicableFixerAmount- 设置运行中文件修复器的已完成操作总数。incrementRunningFileFixer- 增加已完成操作的数量。logProgress- 每秒记录一次升级进度。$FileFixStats- 已执行/已完成操作的计数器。$Type- 对世界数据执行的升级类型。
WorldUpgrader不再接受WorldDataSTATUS_*消息已合并到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而不是ResourceKeynet.minecraft.world.level.chunk.storageLegacyTagFixer接口已移除RecreatingSimpleRegionStorage不再接受提供的LegacyTagFixerSimpleRegionStorage不再接受提供的LegacyTagFixermarkChunkDone已移除
net.minecraft.world.level.levelgen.structureLegacyStructureDataHandler类已移除StructureFeatureIndexSavedData类已移除
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManagerSTRUCTURE_RESOURCE_DIRECTORY_NAME->STRUCTURE_DIRECTORY_NAME,不是一对一WORLD_STRUCTURE_LISTER,RESOURCE_TEXT_STRUCTURE_LISTER- 结构 nbt 的 ID 转换器。save现在有一个接受路径、StructureTemplate和boolean(是否将数据写为文本)的重载createAndValidatePathToGeneratedStructure->TemplatePathFactory#createAndValidatePathToStructure,不是一对一worldTemplates,testTemplates- 模板路径工厂。
net.minecraft.world.level.levelgen.structure.templatesystem.loaderDirectoryTemplateSource- 某个目录的模板源。ResourceManagerTemplateSource- 资源管理器的模板源。TemplatePathFactory- 获取某个结构路径的工厂。TemplateSource- 结构模板的加载器。
net.minecraft.world.level.storageLevelStorageSourcegetLevelDataAndDimensions现在接受$LevelStorageAccessreadExistingSavedData- 读取任何现有的保存数据。writeGameRules- 将游戏规则写入保存数据。$LevelStorageAccess#releaseTemporarilyAndRun- 释放访问并在重新创建锁之前运行。collectIssues- 收集尝试升级数据时的任何问题。getSummary->fixAndGetSummary,fixAndGetSummaryFromTag;不是一对一getDataTag->getUnfixedDataTag,不是一对一getDataTagFallback->getUnfixedDataTagWithFallback,不是一对一saveDataTag不再接受RegistryAccesssaveLevelData- 保存 level dat。
LevelSummary现在接受是否需要文件修复UPGRADE_AND_PLAY_WORLD- 告诉用户升级他们的世界并游玩的组件。requiresFileFixing- 关卡是否需要文件修复。$BackupStatus#FILE_FIXING_REQUIRED- 是否需要文件修复才能在此版本上玩此关卡。
聊天权限
聊天系统现在有一组相关的权限,指示玩家可以发送或接收哪些消息。Permissions#CHAT_SEND_MESSAGES 和 CHAT_SEND_COMMANDS 分别确定玩家是否可以发送消息或命令。同样,CHAT_RECEIVE_PLAYER_MESSAGES 和 CHAT_RECEIVE_SYSTEM_MESSAGES 确定玩家是否可以接收来自其他玩家或系统的消息。请注意,所有这些权限仅在客户端处理,不在服务器端验证。
net.minecraft.SharedConstants#DEBUG_CHAT_DISABLED- 禁用聊天框的标志。net.minecraft.clientGuiMessage->.multiplayer.chat.GuiMessageGuiMessageTag->.multiplayer.chat.GuiMessageTagMinecraftgetChatStatus->computeChatAbilities,不是一对一$ChatStatus->ChatRestriction,不是一对一
net.minecraft.client.gui.Gui#setChatDisabledByPlayerShown,isShowingChatDisabledByPlayer- 处理聊天是否被显示的玩家禁用。net.minecraft.client.gui.componentsChatComponentGO_TO_RESTRICTIONS_SCREEN- 重定向到限制屏幕的标识符。setVisibleMessageFilter- 设置消息过滤函数。render,captureClickableText现在接受$DisplayMode而不是表示玩家是否在聊天的booleanaddMessage现在是 private- 拆分为
addClientSystemMessage,addServerSystemMessage,addPlayerMessage
- 拆分为
$DisplayMode- 聊天应如何显示。
CommandSuggestionsUSAGE_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.chatChatAbilities- 玩家在聊天框上聊天的限制集。ChatListenerhandleSystemMessage的boolean现在用于表示系统是否为远程而不是覆盖- 覆盖现在通过
handleOverlay处理
- 覆盖现在通过
GuiMessageSource- 消息的来源。
net.minecraft.client.player.LocalPlayer现在接受ChatAbilitieschatAbilities,refreshChatAbilities- 处理聊天能力。
net.minecraft.server.permissions.PermissionsCHAT_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.RegistriesCAT_SOUND_VARIANT- 猫应发出的声音的注册表键。CHICKEN_SOUND_VARIANT- 鸡应发出的声音的注册表键。COW_SOUND_VARIANT- 牛应发出的声音的注册表键。PIG_SOUND_VARIANT- 猪应发出的声音的注册表键。
net.minecraft.network.synched.EntityDataSerializersCAT_SOUND_VARIANT- 猫应发出的声音的实体序列化器。CHICKEN_SOUND_VARIANT- 鸡应发出的声音的实体序列化器。COW_SOUND_VARIANT- 牛应发出的声音的实体序列化器。PIG_SOUND_VARIANT- 猪应发出的声音的实体序列化器。
net.minecraft.sounds.SoundEventsCAT_*声音现在是Holder$Reference或存储在CAT_SOUNDS映射中CHICKEN_*声音现在是Holder$Reference或存储在CHICKEN_SOUNDS映射中COW_*声音存储在COW_SOUNDS映射中PIG_*声音现在是Holder$Reference或存储在PIG_SOUNDS映射中
net.minecraft.world.entity.animal.chickenChickenSoundVariant- 鸡变体播放的声音。ChickenSoundVariants- 所有原版鸡变体。
net.minecraft.world.entity.animal.cowAbstractCow#getSoundSet- 获取牛发出的声音。CowSoundVariant- 牛变体播放的声音。CowSoundVariants- 所有原版牛变体。
net.minecraft.world.entity.animal.felineCatSoundVariant- 猫变体播放的声音。CatSoundVariants- 所有原版猫变体。
net.minecraft.world.entity.animal.chickenChickenSoundVariant- 鸡变体播放的声音。ChickenSoundVariants- 所有原版鸡变体。
net.minecraft.world.entity.animal.pigPigSoundVariant- 猪变体播放的声音。PigSoundVariants- 所有原版猪变体。
音频变更
音频设备现在通过 DeviceTracker 处理,根据底层机器,允许机器在音频设备更改时发送系统事件,或使用标准轮询间隔重新查询可用设备列表。
com.mojang.blaze3d.audioAbstractDeviceTracker- 用于管理音频设备更改的抽象跟踪器。CallbackDeviceTracker- 使用 SOFT 系统事件回调确定更改的设备跟踪器。DeviceList- 所有音频设备的列表,包括默认设备(如果可用)。DeviceTracker- 用于管理音频设备更改的接口。LibraryNO_DEVICE现在是public而不是privateinit现在接受DeviceListgetDefaultDeviceName移至DeviceList#defaultDevicegetCurrentDeviceName->currentDeviceNamehasDefaultDeviceChanged移至AbstractDeviceTracker,不是一对一getAvailableSoundDevices移至DeviceList,不是一对一createDeviceTracker- 创建用于管理音频设备更改的跟踪器。getDebugString->getChannelDebugString
PollingDeviceTracker- 使用轮询间隔确定更改的设备跟踪器。SoundBufferformat- 声音流的格式。size- 声音流中的字节数。isValid- 声音流是否处于有效状态。
net.minecraft.client.OptionsDEFAULT_SOUND_DEVICE现在是private而不是publicisSoundDeviceDefault- 检查设备是否为默认音频设备。
net.minecraft.client.gui.components.debugDebugEntrySoundCache- 显示已加载声音流当前缓存的调试条目。DebugScreenEntries#SOUND_CACHE- 声音流缓存调试信息的标识符。
net.minecraft.client.soundsSoundBufferLibraryenumerate- 循环所有缓存的声音,输出其 id、大小和格式。$DebugOutput- 接受某些声音元数据的接口。$Counter- 跟踪声音流数量和总大小的输出实现。
SoundEnginegetDebugString->getChannelDebugString,getSoundCacheDebugStats; 不是一对一$DeviceCheckState已移除
SoundManager#getDebugString->getChannelDebugString,getSoundCacheDebugStats; 不是一对一
输入消息编辑器支持
Minecraft 现在支持输入消息编辑器(IME),允许输入来自中文或印地语等语言的复杂字符,而不是临时的预编辑文本。预编辑文本在游戏内显示为覆盖层,而主机操作系统提供的任何其他 IME 功能。通过此添加,可以通过 GuiEventListener#preeditUpdated 在屏幕中添加支持,或使用实现该方法的现有原版小部件。
com.mojang.blaze3d.platformInputConstants#setupKeyboardCallbacks现在接受GLFWCharCallbackI而不是GLFWCharModsCallbackI用于字符键入回调,GLFWPreeditCallbackI用于通过输入方法编辑器处理复杂字符输入,以及GLFWIMEStatusCallbackI用于通知编辑器的状态MessageBox- 用于创建操作系统原生消息框的工具。TextInputManager- 用于处理游戏窗口中文本输入的管理器。setTextInputArea- 设置预测文本光标应出现的区域。startTextInput,stopTextInput- 处理切换输入消息编辑器。
net.minecraft.clientKeyboardHandlerresubmitLastPreeditEvent- 重复发送的最后一个预编辑事件。submitPreeditEvent- 告知监听器预编辑文本已更新。
MinecrafttextInputManager- 返回输入管理器。onTextInputFocusChange- 根据文本输入是否聚焦更改编辑器输入状态。
net.minecraft.client.gui.GuiGraphicssetPreeditOverlay- 设置绘制预编辑文本的覆盖层。renderDeferredElements现在接受鼠标位置的int和游戏时间增量刻float
net.minecraft.client.gui.componentsIMEPreeditOverlay- 用于显示输入消息编辑器预编辑文本的覆盖层。TextCursorUtils- 绘制文本光标的工具。
net.minecraft.client.gui.components.events.GuiEventListener#preeditUpdated- 监听预编辑文本何时更改。net.minecraft.client.inputCharacterEvent不再接受修饰符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.cauldronCauldronInteraction- 所有关于将交互注册到映射的字段已移至
CauldronInteractionsINTERACTIONS->CauldronInteractions#ID_MAPPER,现在是private
DEFAULT- 与炼药锅的默认交互$InteractionMap->$Dispatcher,不是一对一
- 所有关于将交互注册到映射的字段已移至
CauldronInteractions- 所有原版炼药锅交互。
基于规则的方块状态提供者
RuleBasedStateProvider 现在扩展了 BlockStateProvider,允许它在需要状态提供器的任何地方使用。其实现没有改变,现在只需要将 rule_based_state_provider 指定为 type。因此,所有使用 RuleBasedBlockStateProvider 的配置都已放宽,以允许任何 BlockStateProvider。
net.minecraft.world.level.levelgen.feature.configurationsDiskConfiguration现在接受一个BlockStateProvider而不是RuleBasedBlockStateProviderTreeConfiguration现在接受一个BlockStateProvider而不是RuleBasedBlockStateProviderbelowTrunkProvider现在是BlockStateProvider而不是RuleBasedBlockStateProvider$TreeConfigurationBuilder现在接受一个BlockStateProvider而不是RuleBasedBlockStateProvider
net.minecraft.world.level.levelgen.feature.stateprovidersBlockStateProvider#getOptionalState- 获取方块的状态,否则为null。BlockStateProviderType#RULE_BASED_STATE_PROVIDER- 基于规则的状态提供器的类型。RuleBasedBlockStateProvider->RuleBasedStateProvider,现在是一个类,实现BlockStateProvider- 构造函数现在可以接受一个可空的回退
BlockStateProvider ifTrueThenProvide- 如果谓词为真,则提供给定的方块。simple->always$Builder- 用于构建放置方块规则的构建器。
- 构造函数现在可以接受一个可空的回退
流体逻辑重组
通用实体流体移动已移至单独的 EntityFluidInteraction 类中,其中所有跟踪的流体都会更新,然后在层时间可能被水流推动。
net.minecraft.world.entityEntityupdateInWaterStateAndDoFluidPushing->updateFluidInteraction,不是一对一updateFluidHeightAndDoFluidPushing->EntityFluidInteraction#updategetFluidInteractionBox- 获取实体在流体交互期间的边界框。modifyPassengerFluidInteractionBox- 返回实体骑乘在某些交通工具中时修改后的边界框。
EntityFluidInteraction- 用于管理实体流体交互和基本移动的处理程序。
net.minecraft.world.level.chunk.LevelChunkSection#hasFluid- 区块部分是否包含流体方块。
移除随机斑块特征
随机斑块特征已被完全移除,转而使用像大多数其他特征一样的位置放置。要转换,配置中定义为 ConfiguredFeature 的部分应该是它自己的文件。然后,位置放置应指定 CountPlacement,后跟使用 TrapezoidInt 的 RandomOffsetPlacement,最后是 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.featuresFeatureUtils#simpleRandomPatchConfiguration,simplePatchConfiguration已移除- 通常被
Feature#SIMPLE_BLOCK替换,带有随机偏移和过滤器的位置放置
- 通常被
NetherFeatures#PATCH_*字段不再有PATCH_*前缀VegetationFeaturesPATCH_*字段不再有PATCH_*前缀WILDFLOWERS_BIRCH_FOREST,WILDFLOWERS_MEADOW->WILDFLOWER,不是一对一PALE_FOREST_FLOWERS->PALE_FOREST_FLOWER
net.minecraft.world.level.biome.BiomeGenerationSettings#getFlowerFeatures->getBoneMealFeaturesnet.minecraft.world.level.levelgen.featureConfiguredFeature#getFeatures->getSubFeatures,现在返回一个持有者包装的ConfiguredFeature流,不包含此特征FeatureFLOWER,NO_BONEMEAL_FLOWER已移除RANDOM_PATCH已移除
RandomPatchFeature类已移除
net.minecraft.world.level.levelgen.feature.configurationsFeatureConfiguration#getFeatures->getSubFeatures,现在返回一个持有者包装的ConfiguredFeature流RandomPatchConfiguration记录已移除
net.minecraft.world.level.levelgen.placement.PlacedFeature#getFeatures现在返回一个持有者包装的ConfiguredFeature流,并连接了此特征
特定逻辑变更
- 画中画提交调用现在使用
0xF000F0而不是0x000000作为光照坐标。 net.minecraft.client.multiplayer.RegistryDataCollector#collectGameRegistries的boolean参数现在仅处理从同步注册表以及标签更新组件。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_featuresJSON 中的字段已重命名为generate_structures以匹配其 Java 字段名称。net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate#ONLY_IN_AIR_PREDICATE现在匹配空气标签而不是仅仅空气方块。net.minecraft.world.level.timersFunctionCallback,FunctionTagCallback现在在序列化时使用id而不是NameTimerCallbacks现在在序列化时使用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:blockbamboo_plantable_on->supports_bamboomushroom_grow_block->overrides_mushroom_light_requirementsmall_dripleaf_placeable->supports_small_dripleafbig_dripleaf_placeable->supports_big_dripleafdry_vegetation_may_place_on->supports_dry_vegetationsnow_layer_cannot_survive_on->cannot_support_snow_layersnow_layer_can_survive_on->support_override_snow_layerenables_bubble_column_drag_downenables_bubble_column_push_upsupports_vegetationsupports_cropssupports_stem_cropssupports_stem_fruitsupports_pumpkin_stemsupports_melon_stemsupports_pumpkin_stem_fruitsupports_melon_stem_fruitsupports_sugar_canesupports_sugar_cane_adjacentlysupports_cactussupports_chorus_plantsupports_chorus_flowersupports_nether_sproutssupports_azaleasupports_warped_fungussupports_crimson_fungussupports_mangrove_propagulesupports_hanging_mangrove_propagulesupports_nether_wartsupports_crimson_rootssupports_warped_rootssupports_wither_rosesupports_cocoasupports_lily_padsupports_frogspawnsupport_override_cactus_flowercannot_support_seagrasscannot_support_kelpgrows_cropsmudmoss_blocksgrass_blockssubstrate_overworldbeneath_tree_podzol_replaceablebeneath_bamboo_podzol_replaceablecannot_replace_below_tree_trunkice_spike_replaceableforest_rock_can_place_onhuge_brown_mushroom_can_place_onhuge_red_mushroom_can_place_onprevents_nearby_leaf_decay
minecraft:enchantmenttrades/desert_special已移除trades/jungle_special已移除trades/plains_special已移除trades/savanna_special已移除trades/snow_special已移除trades/swamp_special已移除trades/taiga_special已移除
minecraft:entity_typecannot_be_age_locked
minecraft:fluidsupports_sugar_cane_adjacentlysupports_lily_padsupports_frogspawnbubble_column_can_occupy
minecraft:itemmetal_nuggetsdyeable已移除,拆分为:dyesloom_dyesloom_patternscauldron_can_remove_duecat_collar_dyeswolf_collar_dyes
mudmoss_blocksgrass_blocks
minecraft:potiontradable
minecraft:worldgen/configured_featurecan_spawn_from_bone_meal
添加列表
net.minecraft.advancements.criterionFoodPredicate- 可以检查食物水平和饱和度的标准谓词。MinMaxBoundsvalidateContainedInRange- 返回一个验证目标范围并将结果作为数据结果返回的函数。$Bounds#asRange- 将边界转换为Range。
net.minecraft.clientMinecraft#sendLowDiskSpaceWarning- 发送系统通知以提示磁盘空间不足。Options#keyDebugLightmapTexture- 显示光照图纹理的键映射。
net.minecraft.client.gui.componentsAbstractScrollAreascrollbarWidth- 滚动条的宽度。defaultSettings- 根据滚动速率构建默认滚动条设置。$ScrollbarSettings- 包含滚动条元数据的记录。
DebugScreenOverlayshowLightmapTexture- 是否在覆盖层上渲染光照图纹理。toggleLightmapTexture- 切换是否应渲染光照图纹理。
ScrollableLayoutsetMinHeight- 设置容器布局的最小高度。$ReserveStrategy- 在布局内保留滚动条宽度时使用的策略。
Tooltipcomponent- 要显示的工具提示的组件。style- 用于计算工具提示背景和框架的标识符。
net.minecraft.client.gui.components.debugDebugEntryDetailedMemory- 显示详细内存使用情况的调试条目。DebugEntryLookingAt#getHitResult- 获取相机实体的命中结果。DebugEntryLookingAtEntityTags- 用于显示实体标签的调试条目。DebugScreenEntriesDETAILED_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.optionsDifficultyButtons- 一个包含创建难度按钮的布局元素的类。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.rendererLightmapRenderStateExtractor- 提取光照图的渲染状态。UiLightmap- 用户界面中的光照图。RenderPipelinesLINES_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.predicatesDataComponentPredicates#VILLAGER_VARIANT- 检查村民类型的谓词。VillagerTypePredicate- 检查村民类型的谓词。
net.minecraft.core.dispenser.SpawnEggItemBehavior- 刷怪蛋的发射器行为。net.minecraft.core.registries.ConcurrentHolderGetter- 从本地缓存读取引用的获取器,必要时同步到原始数据。net.minecraft.dataBlockFamiliesEND_STONE- 末地石变体的家族。getFamily- 获取基础方块的家族(如果存在)。
BlockFamily$Builder#tiles,$Variant#TILES- 作为某个基础方块的瓷砖变体的方块。$Builder#bricks,$Variant#BRICKS- 作为某个基础方块的砖块变体的方块。$Builder#cobbled,$Variant#COBBLED- 作为某个基础方块的圆石变体的方块。
DataGenerator$Uncached- 不缓存任何关于生成文件信息的数据生成器。
net.minecraft.data.recipes.RecipeProviderbricksBuilder,tilesBuilder- 用于砖块和瓷砖方块变体的构建器。generateCraftingRecipe,generateStonecutterRecipe- 为给定的方块家族生成适当的配方。getBaseBlock->getBaseBlockForCraftingbredAnimal- 如果玩家已使两只动物繁殖,则解锁配方。
net.minecraft.gametest.frameworkGameTestEvent#createWithMinimumDelay- 创建一个具有最小延迟的测试事件。GameTestHelpergetBoundsWithPadding- 获取带有指定填充的测试区域的边界框。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.gameClientboundGameRuleValuesPacket- 以字符串形式向客户端发送游戏规则值的数据包。ClientboundGamePacketListener#handleGameRuleValues- 处理从服务器发送的游戏规则值。ClientboundLowDiskSpaceWarningPacket- 发送给客户端警告机器磁盘空间不足的数据包。ClientGamePacketListener#handleLowDiskSpaceWarning- 处理关于磁盘空间不足的警告数据包。ServerboundAttackPacket- 发送给服务器关于玩家攻击了哪个实体的数据包。ServerboundClientCommandPacket$Action#REQUEST_GAMERULE_VALUES- 从服务器请求游戏规则值。ServerboundSetGameRulePacket- 从客户端发送设置游戏规则条目的数据包。ServerboundSpectateEntityPacket- 发送给服务器关于玩家想要旁观哪个实体的数据包。ServerGamePacketListenerhandleAttack- 处理玩家对实体的攻击。handleSpectateEntity- 处理玩家想要旁观实体。handleSetGameRule- 处理从客户端设置游戏规则。
net.minecraft.resourcesFileToIdConverter#extensionMatches- 检查标识符是否以指定的扩展名结尾。IdentifierALLOWED_NAMESPACE_CHARACTERS- 标识符命名空间中允许的字符。resolveAgainst- 通过检查/<namespace>/<path>从给定根解析路径。
net.minecraft.serverBootstrap#shutdownStdout- 关闭 stdout 流。MinecraftServerDEFAULT_GAME_RULES- 服务器的默认游戏规则。warnOnLowDiskSpace- 如果磁盘空间低于 64 MiB,则发送警告。sendLowDiskSpaceWarning- 发送磁盘空间不足的警告。
net.minecraft.server.commands.SwingCommand- 调用所有目标的LivingEntity#swing的命令。net.minecraft.server.level.ServerPlayersendBuildLimitMessage- 如果玩家在相应的 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.utilARGB#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.attributeAttributeType#toFloat- 将属性值作为float获取,如果未定义则抛出异常。AttributeTypes#INTEGER- 一个整数属性类型。LerpFunction#ofInteger- 用于整数值的 lerp 函数。
net.minecraft.world.attribute.modifierAttributeModifier#INTEGER_LIBRARY- 用于整数的操作符库。IntegerModifier- 将某些参数应用于整数值的修饰符。
net.minecraft.world.entityAgeableMobAGE_LOCK_COOLDOWN_TICKS- 在实体可以年龄锁定/解锁之前等待的 tick 数。ageLockParticleTimer- 年龄锁定/解锁时显示粒子的时间。
EntityapplyEffectsFromBlocksForLastMovements- 对实体应用上一次移动的方块效果,由物品使用。$Flags- 一个注解,标记特定值为实体的标志位集。
LivingEntity#getLiquidCollisionShape- 返回实体尝试与液体碰撞时的边界。MobasValidTarget- 检查实体是否为该实体的有效目标(可以攻击)。getTargetUnchecked- 获取原始目标而不检查其有效性。canAgeUp- 实体是否可以成长为更成熟的变体。setAgeLocked,isAgeLocked- 实体是否不能成长。
NeutralMob#getTargetUnchecked- 获取原始目标而不检查其有效性。TamableAnimal#feed- 玩家将物品作为食物给予,根据存储的组件或某些默认值治愈它们。
net.minecraft.world.entity.ai.behaviorBehaviorControl#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.LeashFenceKnotEntitygetKnot- 在给定位置找到结,否则返回空的可选值。createKnot- 创建一个新结并将其添加到关卡中。
net.minecraft.world.entity.monster.piglinPiglinAiMAX_TIME_BETWEEN_HUNTS- 猪灵再次开始狩猎前的最大秒数。findNearbyAdultPiglins- 返回此猪灵记忆中所有成年猪灵的列表。
net.minecraft.world.entity.raid.RaidgetBannerComponentPatch- 获取旗帜图案的组件。getOminousBannerTemplate- 获取不祥旗帜的堆叠模板。
net.minecraft.world.inventory.SlotRangesMOB_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.stateBlockBehaviour$PostProcess- 一个获取要标记为后处理的位置的接口。StateDefinitionpropertiesCodec- 状态属性的映射编解码器。isSingletonState- 定义是否只包含一个状态。
StateHolder#isSingletonState- 持有者是否只包含一个状态。
net.minecraft.world.level.block.state.propertiesNoteBlockInstrumentTRUMPET- 铜块放置在音符盒下时发出的声音。TRUMPET_EXPOSED- 斑驳的铜块放置在音符盒下时发出的声音。TRUMPET_OXIDIZED- 氧化的铜块放置在音符盒下时发出的声音。TRUMPET_WEATHERED- 锈蚀的铜块放置在音符盒下时发出的声音。
Property$Value#valueName- 获取值的名称。
net.minecraft.world.level.dimension.DimensionDefaultsBLOCK_LIGHT_TINT- 方块光的默认着色。NIGHT_VISION_COLOR- 夜视激活时的默认颜色。TURTLE_EGG_HATCH_CHANCE- 海龟蛋在随机 tick 中孵化的几率。
net.minecraft.world.level.gamerules.GameRule#getIdentifierWithFallback- 获取游戏规则的标识符,否则获取未注册的标识符。net.minecraft.world.level.levelgenNoiseBasedChunkGenerator#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.materialFluidState#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.functionsEnchantRandomlyFunction$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.numberEnvironmentAttributeValue- 以浮点数形式获取属性值的提供器。Sum- 对所有提供的数字提供器的值求和的提供器。
net.minecraft.world.phys.AABB$Builder#isDefined- 检查是否至少有一个点构成边界框。
更改列表
net.minecraft.advancements.criterionEntityTypePredicate#matches现在接受一个持有者包装的EntityType而不是原始类型本身KilledTrigger$TriggerInstance#entityPredicate->entityPlayerPredicate现在接受一个FoodPredicate- 可以使用
PlayerPredicate$Builder#setFood设置
- 可以使用
net.minecraft.client.guiGuiGraphicsblit现在有一个接受GpuTextureView和GpuSampler的重载setTooltipForNextFrame现在有一个接受工具提示的FormattedCharSequence列表以及是否替换任何现有工具提示的重载
ItemSlotMouseAction#onSlotClicked现在接受一个ContainerInput而不是ClickType
net.minecraft.client.gui.componentsAbstractContainerWidget现在接受一个AbstractScrollArea$ScrollbarSettingsAbstractScrollArea现在接受一个AbstractScrollArea$ScrollbarSettingsscrollbarVisible->scrollablescrollBarY现在是 publicscrollRate不再是抽象的
AbstractTextAreaWidget现在接受一个AbstractScrollArea$ScrollbarSettingsPopupScreen$Builder#setMessage->addMessage,不是一对一ScrollableLayout$Container现在接受一个AbstractScrollArea$ScrollbarSettingsTooltip#create现在有一个接受可选的TooltipComponent和样式Identifier的重载
net.minecraft.client.gui.components.debugDebugEntryLookingAtBlock,DebugEntryLookingAtFluid->DebugEntryLookingAt- 更具体地说,
$BlockStateInfo,$BlockTagInfo,$FluidStateInfo,$FluidTagInfo
- 更具体地说,
DebugEntryLookingAtEntity#GROUP现在是 publicDebugScreenEntriesLOOKING_AT_BLOCK->LOOKING_AT_BLOCK_STATE,LOOKING_AT_BLOCK_TAGSLOOKING_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.screensConfirmScreen#layout现在是 finalDemoIntroScreen被ClientPacketListener#openDemoIntroScreen取代,现在是 privateGenericWaitingScreen现在接受三个boolean,分别表示是否显示加载点、取消按钮以及屏幕是否应在按下 ESC 时关闭
net.minecraft.client.gui.screens.inventory.AbstractMountInventoryScreen#mount现在是 finalnet.minecraft.client.gui.screens.optionsOptionsScreen现在实现HasGamemasterPermissionReaction- 构造函数现在接受一个
boolean表示玩家是否当前在世界中 createDifficultyButton现在在WorldOptionsScreen#createDifficultyButtons中处理,不是一对一
- 构造函数现在接受一个
WorldOptionsScreen现在实现HasGamemasterPermissionReactioncreateDifficultyButtons->DifficultyButtons#create,现在是 public
net.minecraft.client.multiplayerClientLevel#syncBlockState现在可以接受一个可空的玩家位置MultiPlayerGameMode#handleInventoryMouseClick现在接受一个ContainerInput而不是ClickTypeWeatherEffectRenderer#render不再接受MultiBufferSource
net.minecraft.client.renderer.block.ModelBlockRenderer$Cache#getLightColor->getLightCoordsnet.minecraft.client.renderer.blockentity.stateBrushableBlockRenderState#itemState现在是 finalEndPortalRenderState现在是一个 final 的Direction集而不是EnumSetShelfRenderState#items现在是 final
net.minecraft.client.renderer.entity.stateFallingBlockRenderState#movingBlockRenderState现在是 finalHumanoidRenderState#attackArm->ArmedEntityRenderState#attackArmWitherRenderState#xHeadRots,yHeadRots现在是 final
net.minecraft.client.resources.sounds.AbstractSoundInstance#random现在是 finalnet.minecraft.commands.SharedSuggestionProvider#getCustomTabSugggestions->getCustomTabSuggestionsnet.minecraft.commands.arguments.ComponentArgument#getResolvedComponent现在接受一个非空的Entitynet.minecraft.commands.arguments.selector.SelectorPattern被CompilableString取代net.minecraft.core.HolderGetter$Provider#get,getOrThrow现在有接受TagKey的重载net.minecraft.dataBlockFamilyshouldGenerateRecipe->shouldGenerateCraftingRecipe,shouldGenerateStonecutterRecipe$Builder#dontGenerateRecipe->dontGenerateCraftingRecipe,generateStonecutterRecipe
DataGenerator现在是抽象的- 构造函数现在只接受
Path输出,不接受WorldVersion或是否总是生成- 原始实现可以在
DataGenerator$Cached中找到
- 原始实现可以在
run现在是抽象的
- 构造函数现在只接受
Main#addServerProviders->addServerDefinitionProviders,不再接受 devboolean,不是一对一- 其余逻辑已放入
addServerConverters,接受 devboolean但不接受报告boolean
net.minecraft.data.loot.BlockLootSubProviderexplosionResistant现在是 privateenabledFeatures现在是 privatemap现在是 private
net.minecraft.data.recipesRecipeProvider$FamilyRecipeProvider->$FamilyCraftingRecipeProvider,$FamilyStonecutterRecipeProviderSingleItemRecipeBuilder#stonecutting移至BlockFamily上的参数
net.minecraft.data.structures.SnbtToNbt现在有一个接受单个输入文件夹路径的重载net.minecraft.gametest.frameworkGameTestHelperassertBlockPresent现在有一个只接受要检查的块的重载moveTo现在有接受BlockPos和Vec3作为位置的重载assertEntityInstancePresent现在有一个通过double膨胀边界框以检查内部实体的重载
GameTestServer#create现在接受一个int表示运行所有匹配测试的次数StructureUtils#testStructuresDir拆分为testStructuresTargetDir,testStructuresSourceDirTestData现在接受一个int表示测试周围填充的方块数
net.minecraft.nbtNbtUtilsaddDataVersion现在使用泛型Dynamic而不是显式的 nbt 标签getDataVersion现在有一个默认值为 -1 的重载(如果未指定版本)
TextComponentTagVisitor现在可以接受一个$Styling和一个boolean表示是否对键进行排序handleEscapePretty现在是一个private实例方法,而不是protectedstatic
net.minecraft.network.FriendlyByteBufreadVec3,writeVec3被Vec3#STREAM_CODEC取代readLpVec3,writeLpVec3被Vec3#LP_STREAM_CODEC取代
net.minecraft.network.chatComponentnbt现在接受一个CompilableString而不是Stringobject现在有一个接受Component回退的重载
ComponentContents#resolve现在接受一个ResolutionContext而不是CommandSourceStack和EntityComponentUtils#updateForEnttiy->resolve,接受ResolutionContext而不是CommandSourceStack和EntityLastSeenMessages#EMPTY现在是 final
net.minecraft.network.chat.contentsNbtContents现在是一个记录,构造函数接受一个CompilableString而不是StringObjectContents现在接受一个可选的Component作为回退,如果其内容无法验证
net.minecraft.network.chat.contents.dataBlockDataSource现在接受一个CompilableString用于Coordinates,而不是模式和编译后的位置EntityDataSource现在接受一个CompilableString用于EntitySelector,而不是模式和编译后的选择器
net.minecraft.network.chat.contents.objects.ObjectInfo#description->defaultFallbacknet.minecraft.network.protocol.gameClientboundSetEntityMotionPacket现在是一个记录ServerboundContainerClickPacket现在接受一个ContainerInput而不是ClickTypeServerboundInteractPacket现在是一个记录,现在接受交互位置的Vec3
net.minecraft.referencesBlocks->BlockIdsItems->ItemIds
net.minecraft.resourcesFileToIdConverter现在是一个记录RegistryDataLoader#load现在返回一个CompletableFuture的冻结注册表访问
net.minecraft.server.MinecraftServer现在接受一个boolean表示是否传播崩溃,通常用于抛出延迟崩溃throwIfFatalException->BlockableEventLoop#throwDelayedException,现在是 private,不是一对一setFatalException->BlockableEventLoop#delayCrash,relayDelayCrash;不是一对一
net.minecraft.server.commands.ChaseCommand#DIMENSION_NAMES现在是 finalnet.minecraft.server.dedicated.DedicatedServerProperties#acceptsTransfers现在是 finalnet.minecraft.server.packsBuiltInMetadata已合并到ResourceMetadata中get->ResourceMetadata#getSectionof->ResourceMetadata#of
PathPackResources#getNamespaces现在有一个接受根目录Path的静态重载VanillaPackResourcesBuilder#setMetadata现在接受一个ResourceMetadata而不是BuiltInMetadata
net.minecraft.server.players.OldUsersConverter#serverReadyAfterUserconversion被areOldUserListsRemoves取代,现在是publicnet.minecraft.tags.TagLoaderloadTagsFromNetwork现在接受一个Registry而不是WritableRegistry,返回标签键到持有者条目列表的映射loadTagsForRegistry现在有一个接受注册表键以及元素查找的重载,返回标签键到持有者条目列表的映射
net.minecraft.utilBrightnesspack->LightCoordsUtil#packblock->LightCoordsUtil#blocksky->LightCoordsUtil#sky
RandomSource#createNewThreadLocalInstance->createThreadLocalInstance- 现在有一个指定种子的重载
Util#copyAndAdd现在有一个接受可变参数元素的重载
net.minecraft.util.threadBlockableEventLoop现在接受一个boolean表示是否传播崩溃,通常用于抛出延迟崩溃ReentrantBlockableEventLoop现在接受一个boolean表示是否传播崩溃,通常用于抛出延迟崩溃
net.minecraft.world.InteractionResult$ItemContext#NONE,DEFAULT现在是 finalnet.minecraft.world.attributeAttributeType现在接受一个ToFloatFunction用于数字提供器ofInterpolated现在接受一个ToFloatFunction
EnvironmentAttributeReader#getValue现在有一个接受LootContext的重载
net.minecraft.world.entityAvatar现在是抽象的EntityfluidHeight现在是 finalgetTags->entityTagsgetRandomY现在有一个指定扩展double的重载
Leashable$Wrench#ZERO现在是 finalLivingEntityinterpolation现在是 finalswingingArm现在是可空的canAttackType->canAttack,不是一对一,接受LivingEntity而不是EntityTypelungeForwardMaybe->postPiercingAttackentityAttackRange->getAttackRangeWith,现在接受用于攻击的ItemStack
net.minecraft.world.entity.ai.behaviorGoAndGiveItemsToTarget现在接受$ItemThrowerthrowItem->BehaviorUtils#throwItem,不是一对一
SpearAttack不再接受接近距离floatTryLaySpawnOnWaterNearLand->TryLaySpawnOnFluidNearLand,不是一对一
net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder#sequence现在接受一个Oneshot作为第二个条目,而不是Triggernet.minecraft.world.entity.ai.goalBoatGoals->FollowPlayerRiddenEntityGoal$FollowEntityGoalBOAT被ENTITY取代
FollowBoatGoal->FollowPlayerRiddenEntityGoal,不是一对一
net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal#targetConditions现在是 finalnet.minecraft.world.entity.ai.sensing.NearestVisibleLivingEntitySensor#getMemory->getMemoryToSetnet.minecraft.world.entity.decoration.Mannequin#getProfile->Avatar#getProfile,现在是public和abstract- 仍在
Mannequin中实现
- 仍在
net.minecraft.world.entity.item.ItemEntity#DEFAULT_HEALTH现在是public而不是privatenet.minecraft.world.entity.monster.breeze.Breeze#idle,slide,slideBack,longJump,shoot,inhale现在是 finalnet.minecraft.world.entity.monster.piglin.PiglinAi#isZombified现在接受Entity而不是EntityTypenet.minecraft.world.entity.monster.warden.Warden#roarAnimationState,sniffAnimationState,emergeAnimationState,diggingAnimationState,attackAnimationState,sonicBoomAnimationState现在是 finalnet.minecraft.world.entity.monster.zombie.Zombie#handleAttributes现在接受EntitySpawnReasonnet.minecraft.world.entity.playerInput#EMPTY现在是 finalPlayercurrentImpulseImpactPos->LivingEntity#currentImpulseImpactPoscurrentExplosionCause->LivingEntity#currentExplosionCausesetIgnoreFallDamageFromCurrentImpulse->LivingEntity#setIgnoreFallDamageFromCurrentImpulseapplyPostImpulseGraceTime->LivingEntity#applyPostImpulseGraceTimeisIgnoringFallDamageFromCurrentImpulse->LivingEntity#isIgnoringFallDamageFromCurrentImpulsetryResetCurrentImpulseContext->LivingEntity#tryResetCurrentImpulseContextresetCurrentImpulseContext->LivingEntity#resetCurrentImpulseContextisInPostImpulseGraceTime->LivingEntity#isInPostImpulseGraceTimeisWithinAttackRange现在接受用于攻击的ItemStack
net.minecraft.world.entity.vehicle.minecart.NewMinecartBehavior$MinecartStep#EMPTY现在是 finalnet.minecraft.world.inventory.AbstractContainerMenu#getQuickCraftPlaceCount现在接受快速制作槽位的数量而不是槽位集本身net.minecraft.world.itemBundleItem#getSelectedItem->getSelectedItemIndexCreativeModeTab$Output现在是protected而不是publicEnderpearlItem#PROJECTILE_SHOOT_POWER现在是 finalItem$Properties#requiredFeatures现在有一个接受FeatureFlagSet的重载Items#register*方法现在是private而不是publicItemUtils#onContainerDestroyed现在接受一个Stream的ItemStack而不是IterableSignApplicator#tryApplyToSign,canApplyToSign现在接受正在使用的ItemStackSnowballItem#PROJECTILE_SHOOT_POWER现在是 finalThrowablePotionItem#PROJECTILE_SHOOT_POWER现在是 finalWindChargeItem#PROJECTILE_SHOOT_POWER现在是 final
net.minecraft.world.item.alchemy.Potions现在处理Holder$Reference而不是超类Holdernet.minecraft.world.item.componentAttackRangeminRange->minReachmaxRange->maxReachminCreativeRange->minCreativeReachmaxCreativeRange->maxCreativeReach
BundleContentsweight现在返回一个DataResult包装的Fraction而不是原始对象getSelectedItem->getSelectedItemIndex
WrittenBookContenttryCraftCopy->craftCopyresolveForItem,resolve现在接受ResolutionContext和HolderLookup$Provider而不是CommandSourceStack和Player
net.minecraft.world.item.enchantmentConditionalEffect#codec不再接受ContextKeySetEnchantment#doLunge->doPostPiercingAttackEnchantmentHelper#doLungeEffects->doPostPiercingAttackEffectsTargetedConditionalEffect#codec,equipmentDropsCodec不再接受ContextKeySet
net.minecraft.world.item.enchantment.effects.EnchantmentAttributeEffect#CODEC->MAP_CODECnet.minecraft.world.item.equipment.Equippable#canBeEquippedBy现在接受一个持有者包装的EntityType而不是原始类型本身net.minecraft.world.item.trading.VillagerTrades#LIBRARIAN_5_EMERALD_NAME_TAG被LIBRARIAN_5_EMERALD_YELLOW_CANDLE,LIBRARIAN_5_EMERALD_RED_CANDLE取代,不是一对一- 原始交易已移至
WANDERING_TRADER_EMERALD_NAME_TAG
- 原始交易已移至
net.minecraft.world.levelLevelAccessor不再实现LevelReaderLevelHeightAccessor#isInsideBuildHeight现在有一个接受BlockPos的重载
net.minecraft.world.level.blockBigDripleafBlock#canPlaceAt现在接受LevelReader而不是LevelHeightAccessor,并且不再接受旧状态BubbleColumnBlock#updateColumn现在接受气泡柱BlockFireBlock#setFlammable现在是private而不是publicMultifaceSpreader$DefaultSpreaderConfig#block现在是 finalSnowyDirtBlock->SnowyBlockSpreadingSnowyDirtBlock->SpreadingSnowyBlock- 构造函数现在接受
ResourceKey表示“基础”方块,或当雪或任何其他装饰(例如草)被移除时的方块
- 构造函数现在接受
net.minecraft.world.level.block.entity.TestInstanceBlockEntitygetTestBoundingBox- 测试的边界框,按其填充膨胀。getTestBounds- 测试的轴对齐边界框,按其填充膨胀。
net.minecraft.world.level.block.entity.vaultVaultConfig#DEFAULT,CODEC现在是 finalVaultServerData#CODEC现在是 finalVaultSharedData#CODEC现在是 final
net.minecraft.world.level.block.stateBlockBehaviour$BlockStateBase现在接受一个Property和Comparable值的数组,而不是一个值映射,并且不再接受MapCodechasPostProcess->getPostProcessPos,不是一对一
$Properties#hasPostProcess->getPostProcessPos,不是一对一
BlockState现在接受一个Property和Comparable值的数组,而不是一个值映射,并且不再接受MapCodecStateHolder现在接受一个Property和Comparable值的数组,而不是一个值映射,并且不再接受MapCodecpopulateNeighbours->initializeNeighbors,现在是包私有而不是public;不是一对一getValues现在返回一个Property$Value流codec现在接受从某个对象获取状态定义的函数
net.minecraft.world.level.chunk.ChunkAccess#blendingData现在是 finalnet.minecraft.world.level.chunk.storage.SimpleRegionStorage#upgradeChunkTag现在接受一个int表示目标版本net.minecraft.world.level.gameevent.vibrations.VibrationSystem$Data#CODEC现在是 finalnet.minecraft.world.level.gamerules.GameRules现在有一个接受GameRule列表的重载net.minecraft.world.level.levelgenNoiseRouterData#caves不再接受NormalNoise$NoiseParameters的HolderGetterWorldDimensions#keysInOrder现在接受一个LevelStem键的集合而不是一个流
net.minecraft.world.level.levelgen.blockpredicatesTrueBlockPredicate#INSTANCE现在是 finalUnobstructedPredicate#INSTANCE现在是 final
net.minecraft.world.level.levelgen.featureAbstractHugeMushrromFeatureisValidPosition现在接受一个WorldGenLevel而不是LevelAccessorplaceTrunk现在接受一个WorldGenLevel而不是LevelAccessormakeCap现在接受一个WorldGenLevel而不是LevelAccessor
BlockBlobFeature现在使用BlockBlobConfiguration泛型FeatureFOREST_ROCK被BLOCK_BLOB取代ICE_SPIKE被SPIKE取代
IceSpikeFeature->SpikeFeature,不是一对一SpikeFeature现在是EndSpikeFeature,不是一对一NUMBER_OF_SPIKES->EndSpikeFeature#NUMBER_OF_SPIKESgetSpikesForLevel->EndSpikeFeature#getSpikesForLevel
net.minecraft.world.level.levelgen.feature.configurationsHugeMushroomFeatureConfiguration现在是一个记录,接受一个可放置的BlockPredicateSpikeConfiguration->EndSpikeConfiguration现在是一个记录- 原始的
SpikeConfiguration现在用于冰刺,接受要使用的方块,以及放置位置的谓词和是否可以替换存在的方块
- 原始的
TreeConfigurationdirtProvider,forceDirt已被belowTrunkProvider取代dirtProvider通常使用CAN_PLACE_BELOW_OVERWORLD_TRUNKSforceDirt通常使用PLACE_BELOW_OVERWORLD_TRUNKS
$TreeConfigurationBuilderdirtProvider,dirt,forceDirt已被belowTrunkProvider取代
net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacercreateFoliage现在接受一个WorldGenLevel而不是LevelSimulatedReaderplaceLeavesRow,placeLeavesRowWithHangingLeavesBelow现在接受一个WorldGenLevel而不是LevelSimulatedReadertryPlaceExtension,tryPlaceLeaf现在接受一个WorldGenLevel而不是LevelSimulatedReader
net.minecraft.world.level.levelgen.feature.rootplacers.RootPlacer#placeRoots,placeRoot现在接受一个WorldGenLevel而不是LevelSimulatedReadernet.minecraft.world.level.levelgen.feature.stateprovidersBlockStateProvider#getState现在接受WorldGenLevel
net.minecraft.world.level.levelgen.feature.treedecoratorsTreeDecorator$Context现在接受一个WorldGenLevel而不是LevelSimulatedReaderlevel现在返回WorldGenLevel而不是LevelSimulatedReader
net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerplaceTrunk现在接受一个WorldGenLevel而不是LevelSimulatedReadersetDirtAt->placeBelowTrunkBlock,现在接受一个WorldGenLevel而不是LevelSimulatedReaderplaceLog现在接受一个WorldGenLevel而不是LevelSimulatedReaderplaceLogIfFree现在接受一个WorldGenLevel而不是LevelSimulatedReadervalidTreePos现在接受一个WorldGenLevel而不是LevelSimulatedReaderisFree现在接受一个WorldGenLevel而不是LevelSimulatedReader
net.minecraft.world.level.levelgen.placement.BiomeFilter#CODEC现在是 finalnet.minecraft.world.level.levelgen.structure.TemplateStructurePiece#template,placeSettings现在是 finalnet.minecraft.world.level.levelgen.structure.pools.aliasDirectPoolAlias#CODEC现在是 finalRandomGroupPoolAlias#CODEC现在是 finalRandomPoolAlias#CODEC现在是 final
net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings#CODEC现在是 finalnet.minecraft.world.level.levelgen.synth.PerlinNoise#getValue不再接受boolean表示是否展平 Y 值而不是应用频率因子net.minecraft.world.level.material.FluidState现在接受一个Property和Comparable值的数组,而不是一个值映射,并且不再接受MapCodecnet.minecraft.world.level.pathfinder.PathTypeDANGER_POWDER_SNOW->ON_TOP_OF_POWDER_SNOWDANGER_FIRE->FIRE_IN_NEIGHBORDAMAGE_FIRE->FIREDANGER_OTHER->DAMAGING_IN_NEIGHBORDAMAGE_OTHER->DAMAGING,DANGER_TRAPDOOR->ON_TOP_OF_TRAPDOOR
net.minecraft.world.level.saveddata.maps.MapItemSavedData#tickCarriedBy现在接受一个可空的ItemFramenet.minecraft.world.level.storage.loot.functionsEnchantRandomlyFunction现在接受一个boolean表示是否包含来自被附魔堆叠的额外交易成本组件- 通过
$Builder#includeAdditionalCostComponent设置
- 通过
EnchantWithLevelsFunction现在接受一个boolean表示是否包含来自被附魔堆叠的额外交易成本组件- 通过
$Builder#includeAdditionalCostComponent设置 $Builder#fromOptions->withOptions,现在有一个接受可选的HolderSet的重载
- 通过
移除列表
net.minecraft.SharedConstants#USE_WORKFLOWS_HOOKSnet.minecraft.client.data.models.BlockModelGenerators#createGenericCubenet.minecraft.client.Minecraft#delayCrashRawnet.minecraft.client.gui.components.EditBox#setFilternet.minecraft.client.multiplayer.ClientPacketListener#getIdnet.minecraft.client.renderer.SheetsshieldSheetbedSheetshulkerBoxSheetsignSheethangingSignSheetchestSheet
net.minecraft.client.renderer.rendertype.RenderTypes#weathernet.minecraft.data.loot.BlockLootSubProvider(Set, FeatureFlagSet, Map, HolderLookup$Provider)net.minecraft.gametest.framework.StructureUtils#DEFAULT_TEST_STRUCTURES_DIRnet.minecraft.nbt.NbtUtilsaddCurrentDataVersionprettyPrint(Tag)
net.minecraft.server.packs.AbstractPackResources#getMetadataFromStreamnet.minecraft.server.players.PlayerList#getSingleplayerDatanet.minecraft.utilMth#createInsecureUUIDLightCoordsUtil#UI_FULL_BRIGHT
net.minecraft.worldContainerListenerDifficulty#getKeySimpleContainer#addListener,removeListener
net.minecraft.world.entity.ai.memory.MemoryModuleType#INTERACTABLE_DOORSnet.minecraft.world.entity.monster.Zoglin#MEMORY_TYPESnet.minecraft.world.entity.monster.creaking.Creaking#MEMORY_TYPESnet.minecraft.world.entity.monster.hogling.Hoglin#MEMORY_TYPESnet.minecraft.world.itemBundleItem#hasSelectedItemItem#getName()ItemStackisFramed,getFramesetEntityRepresentation,getEntityRepresentation
net.minecraft.world.item.componentBundleContentsgetItemUnsafehasSelectedItem
WrittenBookContent#MAX_CRAFTABLE_GENERATION
net.minecraft.world.level.block.LiquidBlock#SHAPE_STABLEnet.minecraft.world.level.levelgen.featureFeature#isStone,isDirt,isGrassOrDirt
net.minecraft.world.level.levelgen.material.WorldGenMaterialRulenet.minecraft.world.level.storage.loot.functions.SetOminousBottleAmplifierFunction#amplifier
来源与归属声明
本文档树由以下上游迁移指南汇编而成:
- 代码库:
https://github.com/ChampionAsh5357/neoforged-github - 分支:
update/26.1 - 指南根目录:
primers/
本次汇编采用的覆盖范围
编译的直接移植指南包含以下上游迁移步骤:
1.21.1 -> 1.21.2/31.21.2/3 -> 1.21.41.21.4 -> 1.21.51.21.5 -> 1.21.61.21.6 -> 1.21.71.21.7 -> 1.21.81.21.8 -> 1.21.91.21.9 -> 1.21.101.21.10 -> 1.21.111.21.11 -> 26.1
归属说明
根据上游primers/README.md声明:
1.12 - 1.15版本迁移指南由@williewillus编写1.16 - 1.17版本迁移指南由@50ap5ud5编写- 所有新版指南(包括本文采用的)均由
@ChampionAsh5357编写 - 文本翻译由
@Gugle借助@Deepseek编写
许可证说明
复制到本文档树的详细迁移指南仍遵循其上游许可证及归属要求。
具体许可证文本及上游拆分请查阅:
repo/primers/README.mdrepo/primers/LICENSE-CHAMPIONASH5357repo/primers/LICENSE-50AP5UD5repo/primers/LICENSE-WILLIEWILLUS