Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

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

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

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

资源包变更

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

客户端物品

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

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

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

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

基本模型

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

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

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

染色源

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

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

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

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

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

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

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

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

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

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

范围属性模型

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

选择属性模型

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

条件属性模型

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

复合模型

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

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

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

特殊动态模型

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

渲染物品

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

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

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

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

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

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

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

自定义物品模型定义

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

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

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

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

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

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

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

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

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

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

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

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

生物 替换当前物品

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

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

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

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

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

粒子,通过渲染类型渲染

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

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

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

小幅迁移

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

SimpleJsonResourceReloadListener

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

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

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

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

MetadataSectionSerializer,被 Codec 取代

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

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

音乐,现在带有音量控制

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

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

标签变更

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

新增列表

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

变更列表

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

移除列表

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