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.4 -> 1.21.5 模组迁移入门文档

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

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

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

感谢:

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

资源包变更

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

正确处理方块实体的移除

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

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

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

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

体素形状辅助类

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

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

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

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

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

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

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

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

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

推断马鞍:装备变更

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

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

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

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

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

加权列表重做

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

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

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

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

加载票

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

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

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

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

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

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

游戏测试大修

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

环境

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

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

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

游戏规则

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

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

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

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

时间

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

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

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

天气

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

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

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

函数

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

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

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

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

复合

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

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

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

自定义类型

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

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

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

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

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

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

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

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

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

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

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

测试函数

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

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

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

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

测试数据

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

游戏测试实例

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

原始实例

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

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

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

    // 'TestData' 信息

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

基于方块的实例

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

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

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

    // 'TestData' 信息

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

自定义测试

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

public class ExampleTestInstance extends GameTestInstance {

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

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

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

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

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

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

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

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

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

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

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

    // 'TestData' 信息

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

数据组件获取器

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

物品

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

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

实体

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

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

生成条件

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

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

变体数据包注册表

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

对于青蛙、猫或狼:

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

对于猪、奶牛或鸡:

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

对于狼的声音变体:

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

客户端资源

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

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

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

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

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

标签与解析

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

// 对于某个 `CompoundTag` tag

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

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

使用编解码器写入

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

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

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

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

命令解析器

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

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

保存数据,现在带有类型

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

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

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

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

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


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

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

    // 其他方法在此处
}

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

渲染管线重做

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

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

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

抽象化 Open GL

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

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

GpuDevice device = RenderSystem.getDevice();

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

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

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

}

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

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

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

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

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

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

对象引用

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

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

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

public class MyTextureManager {
    
    private final GpuTexture texture;

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

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

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

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

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

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

渲染管线

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

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

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

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

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

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

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

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

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

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

后处理效果

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

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

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

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

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

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


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

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

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

模型重做

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

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

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

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

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

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

方块生成器:变体修改器

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

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

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

小幅迁移

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

实体引用

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

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

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

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

解作用域玩家参数

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

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

组件交互事件

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

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

纹理图集重做

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

例如:

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

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

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

注册表上下文交换器

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

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

重载实例创建

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

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

方块效果应用器

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

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

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

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

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

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

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

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

JOML 后端接口

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

标签变更

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

状态效果字段重命名

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

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

非常技术性的变更

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

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

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

    • 例如:trees_birch_and_oak -> trees_birch_and_oak_leaf_litter

新增列表

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

变更列表

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

移除列表

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