Minecraft 1.21.4 -> 1.21.5 模组迁移入门文档
本文档是一个高层次、非详尽的概述,介绍如何将您的模组从 1.21.4 迁移到 1.21.5。本文不涉及任何特定的模组加载器,只关注原版类的变更。所有提供的名称均使用官方的 Mojang 映射。
本入门文档采用 知识共享署名 4.0 国际许可协议 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。
如果存在任何不正确或缺失的信息,请在本仓库提交 issue,或在 Neoforged Discord 服务器中 @ChampionAsh5357。
感谢:
- @TelepathicGrunt 提供的“非常技术性的变更”部分的信息
- @RogueLogix 对“渲染管线重做”部分的审阅和评论
- @Tslat 发现关于
equipOnInteract的错误
资源包变更
原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 Misode 的版本更新日志 中找到它们的列表。
正确处理方块实体的移除
以前,BlockEntity 会在 BlockBehaviour#onRemove 中处理其所有移除逻辑,包括丢弃任何存储的物品和移除方块实体本身。然而,根据方法的使用方式,由于方块实体的可变状态,可能会导致一些奇怪的行为。出于这个原因,构成移除过程的逻辑已被拆分为两个方法:BlockEntity#preRemoveSideEffects 和 BlockBehaviour#affectNeighborsAfterRemoval。
BlockEntity#preRemoveSideEffects 现在负责在方块实体从等级中移除之前从中移除任何东西。默认情况下,如果 BlockEntity 是一个 Container 实例,它会将容器的内容丢弃到等级中。其他逻辑可以在这里处理,但它通常应避免移除 BlockEntity 本身,除非方块实体的位置倾向于动态变化,例如活塞。
然后,LevelChunk 逻辑将在调用 BlockBehaviour#affectNeighborsAfterRemoval 之前调用 removeBlockEntity。这应该只向其他方块发送更新,指示此方块已从等级中移除。对于 BlockEntity 持有者,可以通过调用 Containers#updateNeighboursAfterDestroy 轻松完成。否则,可能希望根据情况自己调用 Level#updateNeighborsAt。
net.minecraft.world.ContainersupdateNeighboursAfterDestroy- 在销毁指定位置的方块后更新邻居状态。dropContentsOnDestroy已移除,对于Container实例在BlockEntity#preRemoveSideEffects中处理
net.minecraft.world.level.block.entity.BlockEntity#preRemoveSideEffects- 处理在从等级中移除方块实体之前应发生的逻辑。net.minecraft.world.level.block.state.BlockBehaviour#onRemove、$BlockStateBase#onRemove->affectNeighborsAfterRemoval,应只处理更新周围邻居的逻辑,而不是丢弃容器数据
体素形状辅助类
VoxelShape 获得了许多辅助方法,用于对其基本状态进行更常见的变换。有用于创建居中(如果需要)盒子的 Block 方法,以及用于将 VoxelShape 旋转到其适当轴或方向的 Shapes 方法。还有一个 Shapes#rotateAttachFace 方法,用于旋转附着在另一个方块面上的某个 VoxelShape。结果要么存储在某个键到 VoxelShape 的 Map 中,要么在使用 Block#getShapeForEachState 时存储为 Function<BlockState, VoxelShape>。
大多数之前有公开或受保护 VoxelShape 的 Block 子类现在都是私有的,重命名为通常称为 SHAPE 或 SHAPES 的字段。存储的 VoxelShape 也可能在 Function 中,而不是直接存储映射本身。
com.mojang.math.OctahedralGrouppermute- 返回给定轴在指定组内被置换到的轴。fromAngles- 使用提供的 X 和 Y 旋转创建一个组。
net.minecraft.core.Direction$Axis#choose现在有一个接受三个布尔值的重载net.minecraft.world.level.block.Blockboxes- 创建比指定数量多一个的盒子,使用索引作为创建VoxelShape的函数的一部分。cube- 创建一个指定大小的居中立方体。column- 创建一个指定大小的水平居中柱体。boxZ- 创建一个指定大小的垂直居中(围绕 X 轴)的立方体/柱体。getShapeForEachState现在返回一个包装ImmutableMap的Function,还有一个方法只考虑指定的属性而不是所有可能的状态。
net.minecraft.world.phys.shapesDiscreteVoxelShape#rotate- 根据OctahedralGroup的置换旋转体素形状。ShapesblockOccudes->blockOccludesrotate- 根据OctahedralGroup的置换围绕提供的向量(如果未指定则围绕方块中心)旋转给定的体素形状。equal- 检查两个体素形状是否等效。rotateHorizontalAxis- 创建一个轴到VoxelShape的映射,表示围绕 Y 轴旋转的方块。rotateAllAxis- 创建一个轴到VoxelShape的映射,表示围绕任何轴旋转的方块。rotateHorizontal- 创建一个方向到VoxelShape的映射,表示围绕 Y 轴旋转的方块。rotateAll- 创建一个方向到VoxelShape的映射,表示围绕任何轴旋转的方块。rotateAttachFace- 创建一个面到方向到VoxelShape的映射,表示当附着在其他方块面上时围绕 Y 轴旋转的方块。
VoxelShape#move现在有一个接受Vec3i的重载
武器、工具和盔甲:去除冗余
武器、工具和盔甲有很多更新,分别移除了对 SwordItem、DiggerItem 和 ArmorItem 硬编码基类的依赖。这些已被其关联的数据组件取代:WEAPON 用于伤害,TOOL 用于挖掘,ARMOR 用于保护,BLOCKS_ATTACKS 用于盾牌。此外,缺失的属性通常通过设置 ATTRIBUTE_MODIFIERS、MAX_DAMAGE、MAX_STACK_SIZE、DAMAGE、REPAIRABLE 和 ENCHANTABLE 来指定。鉴于几乎所有非特定逻辑都已移至数据组件,这些类现在已被完全移除。使用可用的物品属性方法之一或直接调用 Item$Properties#component 将每个物品设置为武器、工具、盔甲或三者的某种组合。
为类似盾牌的物品构造一个 BlockAttacks 组件:
var blocker = new BlocksAttacks(
// 使用物品时,在格挡效果应用之前等待的秒数。
1.2f,
// 一个标量,用于更改格挡器被禁用的刻数。
// 如果为负数,则格挡器通常不能被禁用。
0.5f,
// 一个减少量列表,说明此格挡器阻挡哪种伤害类型以及阻挡多少。
List.of(
new DamageReduction(
// 应用减少量所需的盾牌水平格挡角度
90f,
// 此减少量应应用的伤害类型集合。
// 当为空时,它适用于所有伤害类型。
Optional.empty(),
// 减少攻击的基础伤害。
1f,
// 表示被阻挡的伤害分数的标量。
0.5f
)
),
// 一个函数,决定要从格挡器中移除多少耐久度。
new ItemDamageFunction(
// 指定从格挡器移除耐久度所需的最小伤害量的阈值。
4f,
// 从格挡器中移除的基础耐久度。
1f,
// 表示要转换为移除耐久度的伤害分数的标量。
0.5f
),
// 一个标签键,包含可以绕过格挡器并对持有实体直接造成伤害的物品。如果为空,则没有物品可以绕过格挡器。
Optional.of(DamageTypeTags.BYPASSES_SHIELD),
// 当格挡器成功减轻一些伤害时播放的声音。
Optional.of(SoundEvents.SHIELD_BLOCK),
// 当格挡器被武器禁用时播放的声音。
Optional.of(SoundEvents.SHIELD_BREAK)
);
为类似剑的物品构造一个 Weapon 组件:
var weapon = new Weapon(
// 从物品中移除的耐久度。
3,
// 当被此武器击中时,`BlocksAttack`s 组件物品应被禁用的秒数。
5f
);
net.minecraft.core.component.DataComponentsUNBREAKABLE现在是一个Unit实例HIDE_ADDITIONAL_TOOLTIP、HIDE_TOOLTIP已被整合到TOOLTIP_DISPLAY中,接受一个TooltipDisplayBLOCKS_ATTACKS- 一个组件,决定持有的物品是否可以阻挡来自某些伤害源的攻击INSTRUMENT现在接受一个InstrumentComponentPROVIDES_TRIM_MATERIAL、PROVIDES_BANNER_PATTERNS处理其关联类型的提供者。BEES现在接受一个Bees组件BREAK_SOUND- 物品损坏时播放的声音。
net.minecraft.data.recipesRecipeProvider#trimSmithing现在接受TrimPattern的键SmithingTrimRecipeBuilder现在接受TrimPattern的持有者
net.minecraft.world.entity.LivingEntityblockUsingShield->blockUsingItemblockedByShield->blockedByItemhurtCurrentlyUsedShield已移除canDisableBlocking->getSecondsToDisableBlocking,不是一对一applyItemBlocking- 应用用物品格挡攻击时所做的伤害减少。isDamageSourceBlocked已移除
net.minecraft.world.entity.player.Player#disableShield->net.minecraft.world.item.component.BlocksAttacks#disablenet.minecraft.world.itemAnimalArmorItem类已移除ArmorItem类已移除AxeItem现在继承ItemBannerPatternItem类已移除DiggerItem类已移除FireworkStarItem类已移除HoeItem现在继承ItemInstrumentItem不再接受标签键ItemgetBreakingSound已移除$Propertiestool- 将物品设置为工具。pickaxe- 将物品设置为镐。sword- 将物品设置为剑。axe- 将物品设置为斧。hoe- 将物品设置为锄。shovel- 将物品设置为锹。trimMaterial- 将物品设置为提供纹饰材料。
ItemStack#getBreakingSound已移除PickaxeItem类已移除ShovelItem现在继承ItemSwordItem类已移除ToolMaterial#applyToolProperties现在接受一个布尔值,表示武器是否可以禁用格挡器(例如盾牌)
net.minecraft.world.item.componentBees- 一个包含蜂巢居住者的组件。BlocksAttacks- 用于用持有的物品格挡攻击的组件。InstrumentComponent- 一个包含乐器播放声音的组件。ProvidesTrimMaterial- 一个为某些盔甲提供要使用的纹饰材料的组件。Tool现在接受一个布尔值,表示该工具是否可以在创造模式下破坏方块Unbreakable类已移除Weapon- 一个数据组件,包含物品可以造成多少伤害以及它禁用格挡器(例如盾牌)的时间。
net.minecraft.world.item.equipmentAllowedEntitiesProvider- 一个函数式接口,用于获取允许处理关联逻辑的实体。ArmorMaterialhumanoidProperties->Item$Properties#humanoidArmoranimalProperties->Item$Properties#wolfArmor、horseArmorcreateAttributes现在是公开的
EquippableequipOnInteract- 当为 true 时,该物品可以在与另一个实体交互时装备到该实体上。saddle- 为马鞍创建一个可装备。equipOnTarget- 将物品装备到目标实体上。
推断马鞍:装备变更
为马鞍添加了一个新的 EquipmentSlot,这带来了用于泛化槽位逻辑的新变化。
首先,现在可以通过一个称为 SimpleEquipmentLayer 的附加 RenderLayer 来处理实体的装备槽位渲染。这接受实体渲染器、EquipmentLayerRenderer、要渲染的层类型、从实体状态获取 ItemStack 的函数,以及成年和幼年模型。渲染器将尝试从关联的可装备数据组件中查找客户端信息,并使用该信息在必要时渲染层。
接下来,实体上不再为每个装备槽位设置单独的列表,而是有一个通用的 EntityEquipment 对象,它持有一个槽位到 ItemStack 的映射委托。这大大简化了存储逻辑。
最后,可装备现在可以通过设置 equipOnInteract 来指定物品是否应在交互时(通常是右键单击)装备到生物上。
net.minecraft.client.modelCamelModelhead现在是公开的createBodyMesh- 创建骆驼的网格定义。
CamelSaddleModel- 带有马鞍的骆驼模型。DonkeyModel#createSaddleLayer- 为带有马鞍的驴创建层定义。EquineSaddleModel- 带有马鞍的马科动物的模型。PolarBearModel#createBodyLayer现在接受一个布尔值,表示实体是否为幼年
net.minecraft.client.renderer.entity.layers.HorseArmorLayer、SaddleLayer->SimpleEquipmentLayernet.minecraft.client.renderer.entity.stateCamelRenderState#isSaddled->saddle,不是一对一EquineRenderState#isSaddled->saddle,不是一对一PigRenderState#isSaddled->saddle,不是一对一SaddleableRenderState类已移除StriderRenderState#isSaddled->saddle,不是一对一CamelRenderState#isSaddled->saddle,不是一对一
net.minecraft.client.resources.model.EquipmentClientInfo$LayerType现在包含:PIG_SADDLESTRIDER_SADDLECAMEL_SADDLEHORSE_SADDLEDONKEY_SADDLEMULE_SADDLEZOMBIE_HORSE_SADDLESKELETON_HORSE_SADDLEtrimAssetPrefix- 返回应用于包含关联类型的盔甲纹饰的纹理的前缀。
net.minecraft.world.entityEntityEquipment- 一个槽位到物品堆栈的映射,表示实体的装备。EquipmentSlotSADDLE、$Type#SADDLEcanIncreaseExperience- 该槽位是否可以在杀死生物时增加获得的经验值数量。
EquipmentSlotGroup现在是一个可迭代对象SADDLEslots- 返回组内的槽位。
LivingEntitygetEquipSound- 获取将物品装备到槽位时要播放的声音。getArmorSlots、getHandSlots、getArmorAndBodyArmorSlots、getAllSlots已移除equipment- 实体穿戴的装备。createEquipment- 设置实体穿戴的默认装备。drop- 丢弃指定的堆栈。getItemBySlot、setItemBySlot不再是抽象的。verfiyEquippedItem已移除
MobisSaddled- 检查马鞍槽位中是否有物品。createEquipmentSlotContainer- 为装备槽位创建一个单物品容器。
OwnableEntity#getRootOwner- 获取实体的最高级所有者。Saddleable接口已移除
net.minecraft.world.entity.animal.horse.AbstractHorsesyncSaddletoClients已移除getBodyArmorAccess已移除
net.minecraft.world.entity.playerInventoryarmor、offhand->EQUIPMENT_SLOT_MAPPING,不是一对一selected现在是私有的setSelectedHotbarSlot->setSelectedSlot- 还存在获取器
getSelectedSlot
- 还存在获取器
getSelected->getSelectedItem- 还存在设置器
setSelectedItem
- 还存在设置器
getNonEquipmentItems- 返回库存中的非装备物品列表。getDestroySpeed已移除getArmor已移除
PlayerEquipment- 玩家穿戴的装备。
net.minecraft.world.itemItem#inventoryTick(ItemStack, Level, Entity, int, boolean)->inventoryTick(ItemStack, ServerLevel, Entity, EquipmentSlot)SaddleItem类已移除
加权列表重做
加权随机列表已被重新设计为一个基本类,用于保存加权条目,以及一个辅助类,可以从对象本身获取权重。
首先是 WeightedList。它实际上是 SimpleWeightedRandomList 的替代品,通过将 Weighted(WeightedEntry 的替代品)条目存储在列表本身中,以完全相同的方式工作。在内部,列表要么存储为对象条目的扁平数组,要么在总权重大于 64 时存储为紧凑加权列表。然后,要获取一个随机元素,可以调用 getRandom 或 getRandomOrThrow 来获取一个条目。如果列表中没有元素,这两个方法都将返回某种形式的空对象或异常。
然后是 WeightedRandom 中的静态辅助方法。这些方法接受原始列表和某个 ToIntFunction,该函数从列表的对象中获取权重。一些方法还接受一个整数,表示要选择的最大索引或与加权索引关联的条目。
net.minecraft.client.resources.model.WeightedBakedModel现在接受WeightedList而不是SimpleWeightedRandomListnet.minecraft.util.randomSimpleWeightedRandomList、WeightedRandomList->WeightedList,现在是 final,不是一对一contains- 检查列表是否包含此元素。
Weight类已移除WeightedEntry->Weighted- 所有
WeightedRandom静态方法现在接受一个ToIntFunction来获取提供的列表中某个条目的权重
net.minecraft.util.valueproviders.WeightedListInt现在接受WeightedListnet.minecraft.world.level.SpawnData#LIST_CODEC现在是一个WeightedList的SpawnDatanet.minecraft.world.level.biomeBiome#getBackgroundMusic现在是一个WeightedList的MusicBiomeSpecialEffects#getBackgroundMusic、$Builder#backgroundMusic现在是一个WeightedList的MusicMobSpawnSettings#EMPTY_MOB_LIST、getMobs现在是一个WeightedList
net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig#spawnPotentialsDefinition、lootTablesToEject现在接受WeightedListnet.minecraft.world.level.chunk.ChunkGenerator#getMobsAt现在返回一个WeightedListnet.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider现在使用WeightedListnet.minecraft.world.level.levelgen.heightproviders.WeightedListHeight现在使用WeightedListnet.minecraft.world.level.levelgen.structure.StructureSpawnOverride现在接受WeightedListnet.minecraft.world.level.levelgen.structure.pools.aliasPoolAliasBinding#random、randomGroup现在接受WeightedListRandom现在接受WeightedListRandomGroup现在接受WeightedList
net.minecraft.world.level.levelgen.structure.structures.NetherFortressStructure#FORTRESS_ENEMIES现在是一个WeightedList
加载票
加载票已被重新实现为一个半类型注册表、半硬编码的系统。使区块在特定时间段内保持加载或模拟的底层逻辑仍然存在;然而,与每个加载票关联的逻辑被硬编码到它们适当的位置,例如强制加载或玩家加载加载票。
加载票从其注册的 TicketType 开始,其中包含有关加载票应持续多少刻(如果永久则为 0)、是否应将加载票保存到磁盘以及加载票的用途的信息。加载票有两种潜在用途:一种用于加载区块并保持其加载,另一种用于根据加载票创建者的预期移动来模拟区块。大多数加载票指定它们同时用于加载和模拟。
有两种特殊类型具有关联的额外行为。TicketType#FORCED 有一些立即加载区块并保持其加载的逻辑。TicketType#UNKNOWN 不能自动超时,意味着除非明确指定,否则它们永远不会被移除。
// 您需要将加载票类型注册到 `BuiltInRegistries#TICKET_TYPE`
public static final TicketType EXAMPLE = new TicketType(
// 加载票被移除前的刻数
// 如果不应移除,则设置为 0
0L,
// 是否应将加载票保存到磁盘
true,
// 加载票的用途
TicketType.TicketUse.LOADING_AND_SIMULATION
);
然后是 Ticket 类,它实际存储在 TicketStorage 中并由其处理。Ticket 类接受加载票的类型,并使用它来自动填充它到期的时间。它还接受加载票等级,通常是一个值 31(用于实体Tick和方块Tick)、32(用于方块Tick)或 33(只能访问静态或修改,不能自然更新)减去可以加载的区块半径。然后通过调用 TicketStorage#addTicketWithRadius 或其委托 ServerChunkCache#addTicketWithRadius 将加载票添加到进程中。如果您希望手动指定加载票而不是根据其半径计算,也可以使用 addTicket。
net.minecraft.server.levelChunkMap现在接受TicketStorage$TrackedEntity#broadcastIgnorePlayers- 将数据包广播给所有玩家,但 UUID 列表中的玩家除外。
DistanceManagerchunksToUpdateFutures现在是 protected,并接受一个TicketStoragepurgeStaleTickets->net.minecraft.world.level.TicketStorage#purgeStaleTicketsgetTicketDebugString->net.minecraft.world.level.TicketStorage#getTicketDebugStringgetChunkLevel- 返回当前区块等级,或当提供的布尔值为 true 时返回模拟等级。getTickingChunks已移除removeTicketsOnClosing已移除$ChunkTicketTracker->LoadingChunkTracker或SimulationChunkTracker
ServerChunkCacheaddRegionTicket->addTicketWithRadius或addTicketremoveRegionTicket->removeTicketWithRadiusremoveTicketsOnClosing->deactivateTicketsOnClosing
Ticket不再是 final,也不再实现Comparable- 构造函数不再接受键
CODECsetCreatedTick、timedOut->resetTicksLeft、decreaseTicksLeft、isTimedOut;不是一对一
TicketType现在是一个记录,不再有泛型getComparator已移除doesLoad、doesSimulate- 检查加载票用途是否用于其特定实例。$TicketUse- 加载票可以用于什么。
TickingTracker->SimulationChunkTracker
net.minecraft.world.level.ForcedChunksSavedData->TicketStoragenet.minecraft.world.level.chunk.ChunkSourceupdateChunkForced现在返回一个布尔值,指示区块是否已被强制加载getForceLoadedChunks- 返回所有已被强制加载的区块。
游戏测试大修
游戏测试已被完全改造为一个基于注册表的系统,与之前自动注解驱动的系统完全不同。然而,使用该系统所需的大多数实现必须由您自己完成,而不是由原版提供。因此,此说明将涵盖整个系统,包括哪些部分需要大量工作才能使其类似于先前版本的注解驱动系统。
环境
所有游戏测试都在某个环境中发生。大多数情况下,测试可以独立于区域进行,但有时环境需要以某种方式进行管理,例如检查实体或方块在给定时间是否执行了某些操作。为了促进给定测试实例的环境设置和拆除,创建了一个 TestEnvironmentDefinition。
TestEnvironmentDefinition 的工作方式类似于 BeforeBatch 和 AfterBatch 注解。环境包含两个方法 setup 和 teardown,用于管理测试的 ServerLevel。环境以基于类型的注册表系统构建,这意味着每个环境将一个 MapCodec 注册到内置注册表 minecraft:test_environment_definition_type,然后通过数据包注册表 minecraft:test_environment 中的 TestEnvironmentDefinition 使用。
默认情况下,原版提供了 minecraft:default 测试环境,它什么都不做。然而,可以使用可用的测试定义类型创建其他测试环境。
游戏规则
此环境类型设置测试要使用的游戏规则。在拆除期间,游戏规则将恢复为其默认值。
// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:game_rules",
// 要设置的具有布尔值的游戏规则列表
"bool_rules": [
{
// 规则的名称
"rule": "doFireTick",
"value": false
}
// ...
],
// 要设置的具有整数值的游戏规则列表
"int_rules": [
{
"rule": "playersSleepingPercentage",
"value": 50
}
// ...
]
}
时间
此环境类型将时间设置为某个非负整数,类似于 /time set <number> 命令的使用方式。
// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:time_of_day",
// 设置世界中的时间
// 常见值:
// - 白天 -> 1000
// - 中午 -> 6000
// - 夜晚 -> 13000
// - 午夜 -> 18000
"time": 13000
}
天气
此环境类型设置天气,类似于 /weather 命令的使用方式。
// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:weather",
// 可以是三个值之一:
// - clear (无天气)
// - rain (雨)
// - thunder (雷雨)
"weather": "thunder"
}
函数
此环境类型提供两个 ResourceLocation 指向 mcfunctions,分别用于设置和拆除等级。
// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:function",
// 要使用的设置 mcfunction
// 如果未指定,则不会运行任何内容
// 指向 'data/examplemod/function/example/setup.mcfunction'
"setup": "examplemod:example/setup",
// 要使用的拆除 mcfunction
// 如果未指定,则不会运行任何内容
// 指向 'data/examplemod/function/example/teardown.mcfunction'
"teardown": "examplemod:example/teardown"
}
复合
如果需要多种组合,则可以使用复合环境类型(恰当地命名为 all_of)将上述多个环境类型串联在一起。
// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
"type": "minecraft:all_of",
// 要使用的测试环境列表
// 可以指定注册表名称或环境本身
"definitions": [
// 指向 'data/minecraft/test_environment/default.json'
"minecraft:default",
{
// 原始环境定义
"type": "..."
}
// ...
]
}
自定义类型
如果上述类型都不起作用,则可以通过实现 TestEnvironmentDefinition 并创建关联的 MapCodec 来创建自定义定义:
public record ExampleEnvironmentType(int value1, boolean value2) implements TestEnvironmentDefinition {
// 构造要注册的映射编解码器
public static final MapCodec<ExampleEnvironmentType> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.INT.fieldOf("value1").forGetter(ExampleEnvironmentType::value1),
Codec.BOOL.fieldOf("value2").forGetter(ExampleEnvironmentType::value2)
).apply(instance, ExampleEnvironmentType::new)
);
@Override
public void setup(ServerLevel level) {
// 在此处设置任何必要的内容
}
@Override
public void teardown(ServerLevel level) {
// 撤消在 setup 方法中更改的任何内容
// 这应恢复到默认值或之前的值
}
@Override
public MapCodec<ExampleEnvironmentType> codec() {
return CODEC;
}
}
然后使用您的模组加载器所需的任何注册表方法注册 MapCodec:
Registry.register(
BuiltInRegistries.TEST_ENVIRONMENT_DEFINITION_TYPE,
ResourceLocation.fromNamespaceAndPath("examplemod", "example_environment_type"),
ExampleEnvironmentType.CODEC
);
最后,您可以在环境定义中使用它:
// examplemod:example_environment
// 在 'data/examplemod/test_environment/example_environment.json'
{
"type": "examplemod:example_environment_type",
"value1": 0,
"value2": true
}
测试函数
游戏测试的最初概念是围绕运行 GameTestHelper 中的函数来判定测试成功或失败。测试函数是这些函数的注册表驱动表示。本质上,每个测试函数都是一个接受 GameTestHelper 的方法。
目前,原版只提供 minecraft:always_pass,它只调用 GameTestHelper#succeed。测试函数也不是生成的,意味着它只是用提供的任何内容运行该值。因此,一个测试函数通常应代表一个旧的游戏测试:
Registry.register(
BuiltInRegistries.TEST_FUNCTION,
ResourceLocation.fromNamespaceAndPath("examplemod", "example_function"),
(GameTestHelper helper) -> {
// 运行您想要的任何游戏测试命令
helper.assertBlockPresent(...);
// 确保有某种方式成功
helper.succeedIf(() -> ...);
}
);
测试数据
现在我们有了环境和测试函数,就可以开始定义我们的游戏测试了。这是通过 TestData 完成的,它相当于 GameTest 注解。唯一的变化是,结构现在通过 structure 由其 ResourceLocation 引用,GameTest#timeoutTicks 现在重命名为 TestData#maxTicks,并且不再指定 GameTest#rotationSteps,而是通过 TestData#rotation 提供 Rotation。其他所有内容保持不变,只是以不同的格式表示。
游戏测试实例
有了 TestData,我们现在可以通过 GameTestInstance 将所有内容链接在一起。这个实例实际上代表了一个单独的测试。再次,原版只提供默认的 minecraft:always_pass,因此我们需要自己构造实例。
原始实例
以前的游戏测试使用 minecraft:function 实现,它将测试函数链接到测试数据。
// examplemod:example_test
// 在 'data/examplemod/test_instance/example_test.json'
{
"type": "minecraft:function",
// 指向测试函数注册表中的 'Consumer<GameTestHelper>'
"function": "examplemod:example_function",
// 'TestData' 信息
// 运行测试的环境
// 指向 'data/examplemod/test_environment/example_environment.json'
"environment": "examplemod:example_environment",
// 用于游戏测试的结构
// 指向 'data/examplemod/structure/example_structure.nbt'
"structure": "examplemod:example_structure",
// 游戏测试将运行直到自动失败的刻数
"max_ticks": 400,
// 用于设置游戏测试所需所有内容的刻数
// 这不计入测试可以进行的最大刻数
// 如果未指定,默认为 0
"setup_ticks": 50,
// 测试是否必须成功才能将批次运行标记为成功
// 如果未指定,默认为 true
"required": true,
// 指定结构和所有后续辅助方法应如何为测试旋转
// 如果未指定,则不旋转任何内容
"rotation": "clockwise_90",
// 当为 true 时,测试只能通过 `/test` 命令运行
// 如果未指定,默认为 false
"manual_only": true,
// 指定测试可以重新运行的最大次数
// 如果未指定,默认为 1
"max_attempts": 3,
// 指定测试必须发生的最小成功次数,才能将测试标记为成功
// 这必须小于或等于允许的最大尝试次数
// 如果未指定,默认为 1
"required_successes": 1,
// 返回结构边界是否应保持顶部为空
// 这目前仅用于基于方块的测试实例
// 如果未指定,默认为 false
"sky_access": false
}
基于方块的实例
原版还通过 minecraft:block_based 提供了一个基于方块的测试实例。这是通过结构处理的,测试方块通过 Level#hasNeighborSignal 接收信号。要开始,结构必须有一个设置为启动模式的测试方块。然后触发该方块,发送一个持续一刻的十五信号脉冲。然后,结构可以有任意数量的测试方块,设置为日志、接受或失败模式。日志测试方块在激活时也会发送十五信号脉冲。接受和失败测试方块如果其中任何一个被激活,则游戏测试成功或失败(成功优先于失败)。
由于此测试依赖于结构中的测试方块,因此除了测试数据之外,不需要额外的信息:
// examplemod:example_test
// 在 'data/examplemod/test_instance/example_test.json'
{
"type": "minecraft:block_based",
// 'TestData' 信息
// 指向 'data/examplemod/test_environment/example_environment.json'
"environment": "examplemod:example_environment",
// 指向 'data/examplemod/structure/example_structure.nbt'
"structure": "examplemod:example_structure",
"max_ticks": 400,
"setup_ticks": 50,
"required": true,
"rotation": "clockwise_90",
"manual_only": true,
"max_attempts": 3,
"required_successes": 1,
"sky_access": false
}
自定义测试
如果您需要实现自己的基于测试的逻辑,无论是使用更动态的功能 还是因为您懒得将所有数据逻辑迁移到新系统,您可以通过扩展 GameTestInstance 并创建关联的 MapCodec 来创建自己的自定义测试实例:
public class ExampleTestInstance extends GameTestInstance {
// 构造要注册的映射编解码器
public static final MapCodec<ExampleTestInstance> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.INT.fieldOf("value1").forGetter(test -> test.value1),
Codec.BOOL.fieldOf("value2").forGetter(test -> test.value2),
TestData.CODEC.forGetter(ExampleTestInstance::info)
).apply(instance, ExampleTestInstance::new)
);
public ExampleTestInstance(int value1, boolean value2, TestData<Holder<TestEnvironmentDefinition>> info) {
super(info);
}
@Override
public void run(GameTestHelper helper) {
// 运行您想要的任何游戏测试命令
helper.assertBlockPresent(...);
// 确保有某种方式成功
helper.succeedIf(() -> ...);
}
@Override
public MapCodec<ExampleTestInstance> codec() {
return CODEC;
}
@Override
protected MutableComponent typeDescription() {
// 提供关于此测试应该是什么的描述
// 应使用可翻译组件
return Component.literal("Example Test Instance");
}
}
然后使用您的模组加载器所需的任何注册表方法注册 MapCodec:
Registry.register(
BuiltInRegistries.TEST_INSTANCE_TYPE,
ResourceLocation.fromNamespaceAndPath("examplemod", "example_test_instance"),
ExampleTestInstance.CODEC
);
最后,您可以在测试实例中使用它:
// examplemod:example_test
// 在 'data/examplemod/test_instance/example_test.json'
{
"type": "examplemod:example_test_instance",
"value1": 0,
"value2": true,
// 'TestData' 信息
// 指向 'data/examplemod/test_environment/example_environment.json'
"environment": "examplemod:example_environment",
// 指向 'data/examplemod/structure/example_structure.nbt'
"structure": "examplemod:example_structure",
"max_ticks": 400,
"setup_ticks": 50,
"required": true,
"rotation": "clockwise_90",
"manual_only": true,
"max_attempts": 3,
"required_successes": 1,
"sky_access": false
}
net.minecraft.client.renderer.blockentityBeaconRenderer现在有一个泛型,接受BlockEntity和BeaconBeamOwner的子类型StructureBlockRenderer->BlockEntityWithBoundingBoxRenderer,不是一对一
net.minecraft.core.registries.Registries#TEST_FUNCTION、TEST_ENVIRONMENT_DEFINITION_TYPE、TEST_INSTANCE_TYPEnet.minecraft.gametest.Main- 游戏测试服务器的入口点。net.minecraft.gametest.frameworkAfterBatch、BeforeBatch注解已移除BlockBasedTestInstance- 用于测试测试方块的测试实例。BuiltinTestFunctions- 包含所有已注册的测试函数。FailedTestTracker- 用于保存所有失败的测试的对象。FunctionGameTestInstance- 用于运行测试函数的测试实例。GameTest注解已移除GameTestAssertException现在继承GameTestExceptionGameTestException- 游戏测试执行期间抛出的异常。GameTestBatch现在接受索引和环境定义,而不是名称和批次设置GameTestBatchFactoryfromTestFunction->divideIntoBatches,不是一对一toGameTestInfo已移除toGameTestBatch现在接受环境定义和索引$TestDecorator- 从测试实例和等级创建测试信息列表。
GameTestEnvironments- 包含用于批处理游戏测试实例的所有环境。GameTestGenerator注解已移除GameTestHelpertickBlock- 在特定位置Tick方块。assertionException- 返回一个在出错时要抛出的新异常。getBlockEntity现在接受一个Class来将方块实体转换为assertBlockTag- 检查该位置的方块是否在提供的标签内。assertBlock现在接受一个方块 -> 组件函数,用于错误消息。assertBlockProperty现在接受Component而不是字符串assertBlockState现在接受什么都不接受、一个方块状态 -> 组件函数或一个提供的组件assertRedstoneSignal现在接受一个提供的组件assertContainerSingle- 断言容器恰好包含一个指定物品。assertEntityPosition、assertEntityProperty现在接受一个组件fail现在接受一个Component作为错误消息assertTrue、assertValueEqual、assertFalse现在接受一个组件
GameTestInfo现在接受一个持有者包装的GameTestInstance而不是TestFunctionsetStructureBlockPos->setTestBlockPosplaceStructure现在不返回任何内容getTestName-id,不是一对一getStructureBlockPos->getTestBlockPosgetStructureBlockEntity->getTestInstanceBlockEntitygetStructureName->getStructuregetTestFunction->getTest、getTestHolder,不是一对一getOrCalculateNorthwestCorner、setNorthwestCorner已移除fail现在接受Component或GameTestException而不是ThrowablegetError现在返回GameTestException而不是Throwable
GameTestInstance- 定义要运行的测试。GameTestInstances- 包含所有已注册的测试。GameTestMainUtil- 用于运行游戏测试服务器的工具。GameTestRegistry类已移除GameTestSequencetickAndContinue、tickAndFailIfNotComplete现在接受一个整数作为刻,而不是 longthenFail现在接受一个提供的GameTestException而不是Throwable
GameTestServer#create现在接受一个可选的字符串和布尔值,而不是测试函数集合和起始位置GeneratedTest- 一个包含要在给定环境下运行的测试和要应用的函数的对象GameTestTicker$State- 一个枚举,包含游戏测试Tick器当前正在执行的状态。GameTestTimeoutException现在继承GameTestExceptionReportGameListener#spawnBeacon已移除StructureBlockPosFinder->TestPosFinderStructureUtilstestStructuresDir现在是一个路径getStructureBounds、getStructureBoundingBox、getStructureOrigin、addCommandBlockAndButtonToStartTest已移除createNewEmptyStructureBlock->createNewEmptyTest,不是一对一getStartCorner、prepareTestStructure、encaseStructure、removeBarriers已移除findStructureBlockContainingPos->findTestContainingPosfindNearestStructureBlock->findNearestTestfindStructureByTestFunction、createStructureBlock已移除findStructureBlocks->findTestBlockslookedAtStructureBlockPos->lookedAtTestPos
TestClassNameArgument已移除TestEnvironmentDefinition- 定义测试运行的环境,通过在等级上适当设置数据。TestFinder不再包含上下文的泛型$Builder#allTests、allTestsInClass、locateByName已移除$Builder#byArgument->byResourceSelection
TestFunction->TestData,不是一对一TestFunctionArgument->net.minecraft.commands.arguments.ResourceSelectorArgumentTestFunctionFinder->TestInstanceFinderTestFunctionLoader- 保存要加载和运行的测试函数列表。UnknownGameTestException- 当游戏测试的错误未知时抛出的异常。
net.minecraft.network.protocol.gameClientboundTestInstanceBlockState- 发送到客户端的数据包,包含测试的状态及其大小。ServerboundSetTestBlockPacket- 发送到服务器的数据包,用于设置测试方块中要运行的信息。ServerboundTestInstanceBlockActionPacket- 发送到服务器的数据包,用于在测试方块中设置测试实例。
net.minecraft.world.entity.player.PlayeropenTestBlock- 打开一个测试方块。openTestInstanceBlock- 为游戏测试实例打开一个测试方块。
net.minecraft.world.level.blockTestBlock- 用于运行游戏测试的方块。TestInstanceBlock- 用于管理单个游戏测试的方块。
net.minecraft.world.level.block.entityBeaconBeamOwner- 一个接口,表示具有信标光束的方块实体。BeaconBlockEntity现在实现BeaconBeamOwnerBeaconBeamSection->BeaconBeamOwner$Section
BoundingBoxRenderable- 一个接口,表示可以渲染任意大小边界框的方块实体。StructureBlockEntity现在实现BoundingBoxRenderableTestBlockEntity- 用于运行游戏测试的方块实体。TestInstanceBlockEntity- 用于管理单个游戏测试的方块实体。
net.minecraft.world.level.block.state.properties.TestBlockMode- 一个用于表示与测试方块关联的游戏测试当前状态的属性。
数据组件获取器
数据组件系统现在可以通过使用 DataComponentGetter 在任意对象上表示。顾名思义,获取器负责从关联的类型键获取组件。方块实体和实体都使用 DataComponentGetter 来允许查询内部数据,例如变体信息或自定义名称。它们都有从另一个持有者收集数据组件的方法(通过 applyImplicitComponents 或 applyImplicitComponent)。方块实体还包含通过 collectImplicitComponents 收集到另一个持有者的方法。
物品
ItemSubPredicate 已被完全替换为 DataComponentPredicate。每个子谓词在系统中都有其适当的对应项。
net.minecraft.advancements.critereon.*->net.minecraft.core.component.predicates.*ItemAttributeModifiersPredicate->AttributeModifiersPredicateItemBundlePredicate->BundlePredicateItemContainerPredicate->ContainerPredicateItemCustomDataPredicate->CustomDataPredicateItemDamagePredicate->DamagePredicateItemEnchantmentsPredicate->EnchantmentsPredicateItemFireworkExplosionPredicate->FireworkExplosionPredicateItemFireworksPredicate->FireworksPredicateItemJukeboxPlayablePredicate->JukeboxPlayablePredicateItemPotionsPredicate->PotionsPredicateItemSubPredicate->DataComponentPredicate,不是一对一SINGLE_STREAM_CODEC
ItemSubPredicates->DataComponentPredicates,不是一对一ItemTrimPredicate->TrimPredicateItemWritableBookPredicate->WritableBookPredicateItemWrittenBookPredicate->WrittenBookPredicate
net.minecraft.advancements.critereonBlockPredicate现在接受一个DataComponentMatchers用于匹配任何委托的组件数据DataComponentMatchers- 一个对DataComponentGetter进行操作的谓词,匹配提供者上的任何精确和部分组件数据。EntityPredicate现在接受一个DataComponentMatchers而不是Optional<DataComponentExactPredicate>ItemPredicate现在接受一个DataComponentMatchers用于匹配任何委托的组件数据NbtPredicate#matches现在接受一个DataComponentGetter而不是ItemStackSingleComponentItemPredicate现在实现DataComponentPredicate而不是ItemSubPredicatematches(ItemStack, T)->matches(T)
net.minecraft.core.componentDataComponentPatchDELIMITED_STREAM_CODEC$CodecGetter- 获取给定组件类型的编解码器。
DataComponentPredicate->DataComponentExactPredicateisEmpty- 检查谓词内的预期组件列表是否为空。
net.minecraft.core.registries.Registries#ITEM_SUB_PREDICATE_TYPE->DATA_COMPONENT_PREDICATE_TYPE,不是一对一net.minecraft.world.item.AdventureModePredicate不再接受一个布尔值来显示在工具提示中net.minecraft.world.itemBannerItem#appendHoverTextFromBannerBlockEntityTag已移除Item#appendHoverText(ItemStack, Item.TooltipContext, List<Component>, TooltipFlag)->appendHoverText(ItemStack, Item.TooltipContext, TooltipDisplay, Consumer<Component>, TooltipFlag),现已弃用ItemStackaddToTooltip现在是公开的addDetailsToTooltip- 将物品的组件详细信息附加到工具提示。
JukeboxPlayable#showInTooltip已移除
net.minecraft.world.item.componentBlockItemStateProperties现在实现TooltipProviderChargedProjectiles现在实现TooltipProviderCustomData#itemMatcher已移除DyedItemColor#showInTooltip已移除FireworkExplosion#addShapeNameTooltip已移除ItemAttributeModifiers#showInTooltip已移除ItemContainerContents现在实现TooltipProviderSeededContainerLoot现在实现TooltipProviderTooltipDisplay- 一个组件,处理物品工具提示中应隐藏的内容。TooltipProvider#addToTooltip现在接受一个DataComponentGetter
net.minecraft.world.item.enchantment.ItemEnchantments#showInTooltip已移除net.minecraft.world.item.equipment.trim.ArmorTrim#showInTooltip已移除net.minecraft.world.item.trading.ItemCost现在接受DataComponentExactPredicate而不是DataComponentPredicatenet.minecraft.world.level.block.Block#appendHoverText已移除net.minecraft.world.level.block.entityBannerPatternLayers现在实现TooltipProviderPotDecorations现在实现TooltipProvider
net.minecraft.world.level.saveddata.maps.MapId现在实现TooltipProvider
实体
由于 EntityPredicate 现在接受一个 DataComponentExactPredicate 来匹配实体上的槽位,一些用于实体变体的 EntitySubPredicate 已转换为存储在持有的物品上的数据组件。
net.minecraft.advancements.critereonEntityPredicate现在接受一个DataComponentExactPredicate来匹配检查的装备槽位EntitySubPredicateAXOLTOL->DataComponents#AXOLOTL_VARIANTFOX->DataComponents#FOX_VARIANTMOOSHROOM->DataComponents#MOOSHROOM_VARIANTRABBIT->DataComponents#RABBIT_VARIANTHORSE->DataComponents#HORSE_VARIANTLLAMA->DataComponents#LLAMA_VARIANTVILLAGER->DataComponents#VILLAGER_VARIANTPARROT->DataComponents#PARROT_VARIANTSALMON->DataComponents#SALMON_SIZETROPICAL_FISH->DataComponents#TROPICAL_FISH_PATTERN、TROPICAL_FISH_BASE_COLOR、TROPICAL_FISH_PATTERN_COLORPAINTING->DataComponents#PAINTING_VARIANTCAT->DataComponents#CAT_VARIANT、CAT_COLLARFROG->DataComponents#FROG_VARIANTWOLF->DataComponents#WOLF_VARIANT、WOLF_COLLARPIG->DataComponents#PIG_VARIANT- 使用变体子谓词的
register已移除 catVariant、frogVariant、wolfVariant已移除$EntityHolderVariantPredicateType、$EntityVariantPredicateType已移除
SheepPredicate不再接受DyeColor
net.minecraft.client.renderer.entity.state.TropicalFishRenderState#variant->patternnet.minecraft.core.componentDataComponentGetter- 一个从某个对象获取数据组件的获取器。DataComponentHolder、DataComponentMap现在继承DataComponentGetterDataComponentExactPredicate现在是一个DataComponentGetter的谓词expect- 一个期望数据组件具有某个值的谓词。test(DataComponentHolder)已移除
DataComponentsSHEEP_COLOR- 绵羊的染料颜色。SHULKER_COLOR- 潜影贝(盒)的染料颜色。COW_VARIANT- 奶牛的变体。CHICKEN_VARIANT- 鸡的变体。WOLF_SOUND_VARIANT- 狼发出的声音。
net.minecraft.world.entityEntity现在实现DataComponentGetterapplyImplicitComponents- 将获取器中的组件应用到实体上。这应由模组制作者覆盖。applyComponentsFromItemStack- 将堆栈中的组件应用到实体上。castComponentValue- 将对象的类型转换为组件类型。setComponent- 将组件数据设置到实体上。applyImplicitComponent- 将组件数据应用到实体上。这应由模组制作者覆盖。applyImplicitComponentIfPresent- 如果获取器中存在该组件,则应用它。
EntityType#appendCustomNameConfig->appendComponentsConfigVariantHolder接口已移除- 因此,相关实体上的所有
setVariant方法都是私有的,而关联的数据也可以从DataComponentGetter获得
- 因此,相关实体上的所有
net.minecraft.world.entity.animalCatVariant#CODECFox$Variant#STREAM_CODECFrogVariant#CODECMushroomCow$Variant#STREAM_CODECParrot$Variant#STREAM_CODECRabbit$Variant#STREAM_CODECSalmon$Variant#STREAM_CODECTropicalFishgetVariant->getPattern$Pattern现在实现TooltipProvider
Wolf->.wolf.WolfWolfVariant->.wolf.WolfVariant,现在是一个记录,接受一个$AssetInfo和一个SpawnPrioritySelectorsWolfVariants->.wolf.WolfVariants
net.minecraft.world.entity.animal.axolotl.Axolotl$Variant#STREAM_CODECnet.minecraft.world.entity.animal.horseLlama$Variant#STREAM_CODECVariant#STREAM_CODEC
net.minecraft.world.entity.animal.wolfWolfSoundVariant- 狼发出的声音。WolfSoundVariants- 所有原版狼声音变体。
net.minecraft.world.entity.decoration.PaintingVARIANT_MAP_CODEC已移除VARIANT_CODEC现在是私有的
net.minecraft.world.entity.npc.VillagerDataHolder#getVariant、setVariant已移除net.minecraft.world.entity.variant.VariantUtils- 用于获取实体变体信息的工具。net.minecraft.world.itemItemStack#copyFrom- 从获取器复制组件。MobBucketItem#VARIANT_FIELD_CODEC->TropicalFish$Pattern#STREAM_CODEC
net.minecraft.world.level.block.entity.BlockEntity#applyImplicitComponents现在接受一个DataComponentGetter$DataComponentInput->DataComponentGetter
net.minecraft.world.level.Spawner方法现在接受CustomData而不是ItemStack本身
生成条件
为了允许实体在给定条件下随机生成变体,添加了一个名为 SPAWN_CONDITION_TYPE 的新注册表。这些接受 SpawnCondition:一个选择器,像一个谓词,接受上下文以查看给定的变体是否可以在那里生成。所有变体都被放入一个列表中,然后根据存储在 SpawnProritySelectors 中的选定优先级进行排序。优先级较高的将首先被检查,相同优先级的多个将按提供的顺序选择。然后,在相同优先级级别上,所有满足条件的变体将被随机选择。
// 对于某个存在生成条件的对象
[
{
// 正在检查的生成条件
"condition": {
"type": "minecraft:biome",
// 将检查变体尝试生成的生物群系是否在森林中
"biomes": "#minecraft:is_forest"
},
// 将首先检查此条件
"priority": 1
},
{
// 表示条件始终为真
"priority": 0
}
]
net.minecraft.core.registries.Registries#SPAWN_CONDITION_TYPEnet.minecraft.world.entity.variantBiomeCheck- 一个生成条件,检查实体是否在给定的生物群系之一中。MoonBrightnessCheck- 一个生成条件,检查月亮的亮度。PriorityProvider- 一个基于某个优先级整数对条件选择器进行排序的接口。SpawnCondition- 检查实体是否可以在该位置生成。SpawnConditions- 可供选择的生成条件。SpawnContext- 一个包含实体生成所在的当前位置、等级和生物群系的对象。SpawnPrioritySelectors- 要针对实体检查的生成条件列表。用于在给定位置随机选择一个变体生成。StructureCheck- 一个生成条件,检查实体是否在结构内。
变体数据包注册表
青蛙、猫、奶牛、鸡、猪、狼和狼的声音变体是数据包注册表对象,意味着现在大多数引用需要通过 RegistryAccess 或 HolderLookup$Provider 实例来引用。
对于青蛙、猫或狼:
// 文件位于:
// - `data/examplemod/frog_variant/example_frog.json`
// - `data/examplemod/cat_variant/example_cat.json`
// - `data/examplemod/wolf_variant/example_wolf.json`
{
// 指向 `assets/examplemod/textures/entity/cat/example_cat.png` 的纹理
"asset_id": "examplemod:entity/cat/example_cat",
"spawn_conditions": [
// 此变体生成的条件
{
"priority": 0
}
]
}
对于猪、奶牛或鸡:
// 文件位于:
// - `data/examplemod/pig_variant/example_pig.json`
// - `data/examplemod/cow_variant/example_cow.json`
// - `data/examplemod/chicken_variant/example_chicken.json`
{
// 指向 `assets/examplemod/textures/entity/pig/example_pig.png` 的纹理
"asset_id": "examplemod:entity/pig/example_pig",
// 定义用于选择渲染猪变体的实体模型的 `PigVariant$ModelType`
"model": "cold",
"spawn_conditions": [
// 此变体生成的条件
{
"priority": 0
}
]
}
对于狼的声音变体:
// 文件位于:
// - `data/examplemod/wolf_sound_variant/example_wolf_sound.json``
{
// 空闲时随机播放的声音事件的注册表名称
"ambient_sound": "minecraft:entity.wolf.ambient",
// 死亡时播放的声音事件的注册表名称
"death_sound": "minecraft:entity.wolf.death",
// 生气时空闲时随机播放的声音事件的注册表名称
"growl_sound": "minecraft:entity.wolf.growl",
// 受伤时播放的声音事件的注册表名称
"hurt_sound": "minecraft:entity.wolf.hurt",
// 空闲时在生命值满的情况下,随机播放(1/3 的概率)的声音事件的注册表名称
"pant_sound": "minecraft:entity.wolf.pant",
// 空闲时在生命值未满的情况下,随机播放(1/3 的概率)的声音事件的注册表名称
"whine_sound": "minecraft:entity.wolf.whine"
}
客户端资源
客户端文件中的原始 ResourceLocation(用于标识符或纹理)正在被定义标识符以及潜在纹理路径的对象所取代。有三个主要对象需要了解:ClientAsset、ModelAndTexture 和 MaterialAssetGroup。
ClientAsset 是一个 id/纹理对,用于指向纹理位置。默认情况下,纹理路径由 id 构造,路径以 textures 为前缀,并以 PNG 扩展名为后缀。
ModelAndTexture 是一个对象/客户端资源对,当渲染器应在多个模型之间选择时使用。通常,渲染器会创建一个对象类型到模型的映射,并提供给 ModelAndTexture 的对象用作映射中的查找键。
MaterialAssetGroup 是一个处理用某些纹饰材料渲染装备资源的处理器。它接受用于叠加到盔甲上的基础纹理,以及针对给定装备资源的任何覆盖。
net.minecraft.advancements.DisplayInfo现在接受一个ClientAsset而不是仅一个ResourceLocation作为背景纹理net.minecraft.client.modelAdultAndBabyModelPair- 保存两个Model实例,表示某个实体的成年和幼年形态。ChickenModel#createBaseChickenModel- 创建默认的鸡模型。ColdChickenModel- 寒冷温度下鸡的变体模型。ColdCowModel- 寒冷温度下奶牛的变体模型。ColdPigModel- 寒冷温度下猪的变体模型。CowModel#createBaseCowModel- 创建奶牛的基础模型。PigModel#createBasePigModel- 创建默认的猪模型。WarmCowModel- 温暖温度下奶牛的变体模型。
net.minecraft.client.renderer.entityChickenRenderer现在继承MobRenderer而不是AgeableMobRendererCowRenderer现在继承MobRenderer而不是AgeableMobRendererPigRenderer现在继承MobRenderer而不是AgeableMobRenderer
net.minecraft.client.renderer.entity.layers.SheepWoolUndercoatLayer- 一个渲染绵羊羊毛底层的层。net.minecraft.client.renderer.entity.stateCowRenderState- 奶牛实体的渲染状态。SheepRenderStategetWoolColor- 返回绵羊羊毛的整数颜色。isJebSheep- 返回绵羊的名称是否包含jeb_前缀。
net.minecraft.core.ClientAsset- 一个包含标识符和指向某个纹理的路径的对象。net.minecraft.data.loot.EntityLootSubProvider#killedByFrogVariant现在接受FrogVariant的HolderGetternet.minecraft.data.tags.CatVariantTagsProvider类已移除net.minecraft.tags.CatVariantTags类已移除net.minecraft.world.entity.animalAbstractCow- 一个代表奶牛(牛)的抽象动物。Chicken#setVariant、getVariant- 处理鸡的变体信息。ChickenVariant- 一个定义给定鸡的通用可渲染信息和生物群系生成的类。ChickenVariants- 保存所有原版鸡变体的键。Cow现在继承AbstractCow。CowVariant- 一个定义给定奶牛的通用可渲染信息和生物群系生成的类。CowVariants- 保存所有原版奶牛变体的键。CatVariant(ResourceLocation)->CatVariant(ClientAsset, SpawnPrioritySelectors)CatVariants- 保存所有原版猫变体的键。FrogVariant->.frog.FrogVariantFrogVariant(ResourceLocation)->FrogVariant(ClientAsset, SpawnPrioritySelectors)
MushroomCow现在继承AbstractCowPigVariant- 一个定义给定猪的通用可渲染信息和生物群系生成的类。TemperatureVariants- 一个接口,保存指示不同温度下实体的ResourceLocation。
net.minecraft.world.entity.variant.ModelAndTexture- 定义带有其关联纹理的模型。net.minecraft.world.item.equipment.trimMaterialAssetGroup- 一个资源定义了一些基础以及基于所穿戴装备的排列。TrimMaterial现在接受MaterialAssetGroup而不是原始基础和覆盖
标签与解析
标签已被重写,移除了任何对类型的直接引用,同时密封并最终确定了相关类。从标签获取值现在返回一个 Optional 包装的条目,除非您调用 get*Or 方法之一,在其中指定默认值。另一方面,对象不接受默认值,而是返回所需标签的空变体。
// 对于某个 `CompoundTag` tag
// 读取一个值
Optional<Integer> value1 = tag.getInt("value1");
int value1Raw = tag.getIntOr("value1", 0);
// 读取另一个对象
Optional<CompoundTag> childTag = tag.getCompound("childTag");
CompoundTag childTagRaw = tag.getCopmoundOrEmpty("childTag");
使用编解码器写入
CompoundTag 现在有使用 Codec 或 MapCodec 进行写入和读取的方法。对于 Codec,它将序列化的数据存储在指定的键内。对于 MapCodec,它将字段合并到顶层标签上。
// 对于某个 Codec<ExampleObject> CODEC 和 MapCodec<ExampleObject> MAP_CODEC
// 我们还有一个 ExampleObject example
CompoundTag tag = new CompoundTag();
// 对于编解码器
tag.store("example_key", CODEC, example);
Optional<ExampleObject> fromCodec = tag.read("example_key", CODEC);
// 对于映射编解码器
tag.store(MAP_CODEC, example);
Optional<ExampleObject> fromMapCodec = tag.read(MAP_CODEC);
命令解析器
packrat 解析器已更新了新的规则和系统,允许命令具有基于解析器的参数。这来自于 CommandArgumentParser,它解析某些语法以返回所需的对象。然后解析器被 ParserBasedArgument 使用,它尝试解析字符串并根据您当前键入的内容构建任何建议。这些都由 Grammar 类处理,它实现了 CommandArgumentParser,使用原子、字典、规则和术语的组合构建。
net.minecraft.commands.ParserUtils#parseJsonnet.minecraft.commands.argumentsComponentArgument现在继承ParserBasedArgumentNbtTagArgument现在继承ParserBasedArgumentStyleArgument现在继承ParserBasedArgument
net.minecraft.commands.arguments.item.ItemPredicateArgument现在继承ParserBasedArgumentnet.minecraft.nbtByteArrayTag,现在是 final,不再接受列表对象ByteTag现在是一个记录CollectionTag现在是一个密封接口,不再继承AbstractList或具有泛型set、add已移除remove现在返回一个Tagget- 返回指定索引处的标签。getElementType已移除size- 返回集合的大小。isEmpty- 返回集合是否没有元素。stream- 流式传输集合的元素。
CompoundTag现在是 finalstore- 将编解码器或映射编解码器写入标签。read- 从标签中读取编解码器或映射编解码器编码的值。getFloatOrDefault、getIntOrDefault、getLongOrDefault- 获取具有关联键的值,如果不存在或抛出异常则返回默认值。storeNullable- 当不为 null 时,使用编解码器将值写入标签。putUUID、getUUID、hasUUID已移除getAllKeys->keySetvalues、forEach- 实现标准的映射操作。- 接受列表对象的
putByteArray、putIntArray已移除 getTagType已移除contains已移除get*、get*Or- 返回键的可选包装对象,如果使用Or方法,则返回指定的默认值。
DoubleTag现在是一个记录EndTag现在是一个记录FloatTag现在是一个记录IntArrayTag,现在是 final,不再接受列表对象IntTag现在是一个记录ListTag,现在是 final,继承AbstractListaddAndUnwrap- 将标签添加到列表中,如果是一个包含单个元素的复合标签,则改为添加内部标签。get*、get*Or- 返回键的可选包装对象,如果使用Or方法,则返回指定的默认值。compoundStream- 返回列表中所有CompoundTag的扁平映射。
LongArrayTag,现在是 final,不再接受列表对象LongTag现在是一个记录NbtIo#readUnnamedTag现在是公开的,用于测试NbtOps现在有一个私有构造函数NbtUtilsgetDataVersion现在有一个接受Dynamic的重载createUUID、loadUUID已移除readBlockPos、writeBlockPos已移除
NumericTag现在是一个实现PrimitiveTag的密封接口getAsLong->longValuegetAsInt->intValuegetAsShort->shortValuegetAsByte->byteValuegetAsDouble->doubleValuegetAsFloat->floatValuegetAsNumber->boxas*- 返回数值的可选包装。
PrimitiveTag- 一个密封接口,表示标签数据是一个原始对象。ShortTag现在是一个记录SnbtGrammar- 用于字符串化 NBT 的解析器创建器。SnbtOperations- 一个包含用于解析某些值的内置操作的辅助工具。StringTag现在是一个记录StringTagVisitorvisit->build,不是一对一handleEscape->handleKeyEscape,现在是私有的
Tag现在是一个密封接口as*-> 尝试将标签转换为其子类型之一,失败时返回空 optional。getAsString->asString,不是一对一
TagParser现在持有一个泛型,引用要解析到的中间对象的类型- 构造函数现在接受一个语法,或者
create从DynamicOps构造语法 AS_CODEC->FLATTENED_CODECparseTag->parseCompoundFully或parseCompoundAsArgument- 其他方法如
parseFully、parseAsArgument解析到某个中间对象 - 这些都是实例方法
- 其他方法如
readKey、readTypedValue已移除
- 构造函数现在接受一个语法,或者
TagType#isValue已移除
net.minecraft.util.parsing.packratCachedParseState- 一个缓存已解析位置并在读取时控制的解析状态。Control#hasCut- 返回语法的控制流对于读取对象是否有 cut。DelayedException- 一个创建要抛出的异常的接口。Dictionaryput现在返回一个NamedRuleput(Atom<T>, Term<S>, Rule.RuleAction<S, T>)->putComplexget->getOtThrow,不是一对一forward- 获取或写入术语到字典。namedWithAlias- 创建一个对命名原子或其别名的新引用。
ErrorCollector$Nop- 一个什么都不做的错误收集器。NamedRule- 一个具有关联名称的规则。ParseState现在是一个接口- 缓存逻辑已移至
CachedParseState scope- 返回解析对象内当前正在分析的范围。parse现在接受NamedRule而不是AtomacquireControl、releaseControl- 处理获取解析期间使用的Control。silent- 返回一个不收集任何错误的ParseState。
- 缓存逻辑已移至
Ruleparse、$RuleAction#run现在返回一个可为 null 的值,而不是 optionalSimpleRuleAction现在实现$RuleAction
Scope#pushFrame、popFrame、splitFrame、clearFrameValues、mergeFrame- 处理将解析术语管理到称为帧的部分中。Termnamed->Dictionary#named,不是一对一repeated、repeatedWithTrailingSeparator、repeatedWithoutTrailingSeparator- 处理类似于 varargs 的重复术语,并将它们放入列表中。positiveLookahead、negativeLookahead- 处理基于后续内容匹配信息的术语。fail- 将术语标记为解析期间失败。
net.minecraft.util.parsing.packrat.commandsCommandArgumentParser- 将字符串解析为与命令一起使用的参数。Grammar现在接受顶部的NamedRule而不是AtomGreedyPatternParseRule- 一个尝试贪婪匹配提供的模式的规则,假设如果某个区域匹配,则可以获得匹配的组。GreedyPredicateParseRule- 一个尝试贪婪匹配接受的字符的规则,确保字符串达到最小大小。NumberRunParseRule- 一个尝试从字符串解析数字的规则。ParserBasedArgument- 一个使用解析器提取值的命令参数。ResourceLookupRule现在接受 id 解析器的NamedRule而不是AtomStringReaderParserState现在继承CachedParsedState- 不再接受
Dictoionary
- 不再接受
StringReaderTerms#characters- 匹配字符串中的多个字符,通常用于捕获小写和大写变体。UnquotedStringParseRule- 一个将序列的一部分作为未引用字符串读取的规则,确保它达到最小大小。
保存数据,现在带有类型
SavedData 已被重写,将其大部分保存和加载逻辑抽象到单独的 SavedDataType 中。这意味着 save 覆盖以及额外的 load 和 factory 方法现在都在 SavedDataType 本身内部处理。
要构造一个 SavedDataType,您需要传入四个参数。首先是字符串标识符,用于解析保存您信息的 .dat 文件。这必须是一个有效的路径。然后是构造函数,当没有信息存在时,它接受 SavedData$Context 来返回您的数据对象的实例。接下来是编解码器,它接受 SavedData$Context 并返回一个用于读取和写入您的保存数据的 Codec。最后是用于数据修复器的 DataFixTypes。由于这是一个静态枚举,如果您计划使用原版数据修复器,您将需要注入到枚举本身中,或者修补 DimensionDataStorage#readTagFromDisk 中的 update 调用以传入 null 值。
// 我们的保存数据实例
public class ExampleSavedData extends SavedData {
// 保存数据类型
public static final SavedDataType<ExampleSavedData> TYPE = new SavedDataType<>(
// 最好用您的模组 id 后跟下划线作为标识符的前缀
// 斜杠会抛出错误,因为文件夹不存在
// 将解析为 `saves/<world_name>/data/examplemod_example.dat`
"examplemod_example",
// 新实例的构造函数
ExampleSavedData::new,
// 用于编码和解码数据的编解码器工厂
ctx -> RecordCodecBuilder.create(instance -> instance.group(
RecordCodecBuilder.point(ctx.levelOrThrow()),
Codec.INT.fieldOf("value1").forGetter(data -> data.value1),
Codec.BOOL.fieldOf("value2").forGetter(data -> data.value2)
).apply(instance, ExampleSavedData::new));
);
private final ServerLevel level;
private final int value1;
private final boolean value2;
// 用于新实例
private ExampleSavedData(ServerLevel.Context ctx) {
this(ctx.levelOrThrow(), 0, false);
}
// 用于编解码器
// 如果不使用 `DimensionDataStorage#set`,构造函数不需要是公开的
private ExampleSavedData(ServerLevel level, int value1, boolean value2) {
this.level = level;
this.value1 = value1;
this.value2 = value2;
}
// 其他方法在此处
}
// 在可以访问 DimensionDataStorage storage 的地方
ExampleSavedData data = storage.computeIfAbsent(ExampleSavedData.TYPE);
net.minecraft.server.ServerScoreboarddataFactory已移除createData现在接受一个$Packed实例
net.minecraft.world.RandomSequencesfactory、load已移除codec- 根据当前世界种子为随机序列构造一个编解码器。
net.minecraft.world.entity.raid.Raids不再接受任何参数getType- 根据当前维度返回保存数据类型。factory已移除tick现在接受ServerLevelgetId- 获取突袭实例的标识符。canJoinRaid不再接受突袭实例load不再接受ServerLevel
net.minecraft.world.level.levelgen.structure.structures.StructureFeatureIndexSavedDatafactory、load已移除type- 返回具有指定 id 的要素保存数据类型。
net.minecraft.world.level.saveddataSavedDatasave已移除$Factory记录已移除$Context- 保存保存数据正在写入的当前上下文。
SavedDataType- 一个表示保存数据类型的记录,包括关于如何构造、保存和加载数据的信息。
net.minecraft.world.level.saveddata.mapsMapIndex现在有一个接受最后一个地图 id 的构造函数factory、load已移除getFreeAuxValueForMap->getNextMapId
MapItemSavedDatafactory、load已移除type- 使用地图 id 的键返回保存数据类型。
net.minecraft.world.level.storage.DimensionDataStorage现在接受一个SavedData$ContextcomputeIfAbsent、get现在只接受SavedDataTypeset现在接受SavedDataType以及数据实例
net.minecraft.world.scores.ScoreboardSaveDataload->loadFrompack- 将数据打包到其保存数据格式中。$Packed- 表示可序列化的打包数据。
渲染管线重做
无论您之前使用的是着色器还是 RenderType,将对象渲染到屏幕的方式都已完全或部分重做。因此,很多事情需要重新解释,下面将进行更深入的探讨。然而,对于不关心细节的人,这里是 TL;DR。
首先,着色器 JSON 不再存在。这被 RenderPipeline 取代,它实际上是一个代码中的替代品。其次,RenderPipeline 强制将大多数任意值转换为对象。例如,您不再存储混合函数模式 id,而是存储一个 BlendFunction 对象。同样,您不再存储或设置直接的纹理对象,而是通过 GpuTexture 进行管理。最后,VertexBuffer 可以通过直接传入 RenderPipeline 并更新消费者中任何必要的统一变量来绘制到帧缓冲区,或者通过传入 RenderType 来绘制。
现在,对于需要细节的人,让我们深入探讨。
抽象化 Open GL
众所周知,Minecraft 一直在抽象化其 OpenGL 调用和常量,此版本也不例外。除 BufferUsage 外,所有对 GL 代码的调用都已移出对象引用,通常通过调用 GlConst$toGl 来获得。然而,随着所有其他渲染重做,有许多变化和复杂性需要学习一个全新的系统,假设您不使用 RenderType。
从头开始,对底层渲染系统的所有调用都通过 GpuDevice,这是一个像 OpenGL 或 Vulkan 这样的渲染库的通用实现的接口。该设备负责创建缓冲区和纹理,执行任何所需的命令。可以通过 RenderSystem 通过 getDevice 获取当前的 GpuDevice,如下所示:
GpuDevice device = RenderSystem.getDevice();
然后,GpuDevice 可以分别使用 createBuffer 和 createTexture 创建带有所需数据的缓冲区或包含要渲染信息的纹理。为冗余起见,缓冲区保存顶点数据,而纹理保存纹理(颜色和深度)数据。您通常应缓存缓冲区或纹理对象以供以后使用,并根据需要更新任何附加数据。作为参考,缓冲区通常通过使用 BufferBuilder 和 ByteBufferBuilder 首先构建 MeshData,然后再将其传递给 createBuffer 来创建。
设置好所需的缓冲区和纹理后,我们如何实际修改将它们渲染到屏幕?这由 CommandEncoder 处理,它也可以通过 GpuDevice#createCommandEncoder 从设备获得。编码器包含熟悉的读写方法,以及一些额外的将纹理清除为给定颜色或直接将纹理 blit 到屏幕(presentTexture)的方法。然而,这里最重要的方法是 createRenderPass。它接受要绘制到屏幕的 GpuTexture 以及背景的默认 ARGB 颜色。此外,它还可以接受深度纹理。这应该使用 try-with-resources 块来创建,如下所示:
// 我们假设您已经构造了一个用于颜色数据的 `GpuTexture` texture
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(this.texture, OptionalInt.of(0xFFFFFFFF))) {
// 在此处设置内容
}
在 RenderPass 内部,您可以设置要使用的 RenderPipeline,它定义了关联的着色器,绑定来自其他目标的任何采样器或设置统一变量,剪切屏幕的一部分以进行渲染,以及设置用于定义要渲染的顶点的顶点和索引缓冲区。最后,可以使用 draw 方法之一将所有内容绘制到屏幕上,提供起始索引和顶点计数。
// 如果缓冲区/纹理尚未创建或缓存,请在此处创建它们
// 在渲染通道打开时,不能运行来自 `CommandEncoder` 的任何方法
RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
GpuBuffer vertexBuffer = RenderSystem.getQuadVertexBuffer();
GpuBuffer indexBuffer = indices.getBuffer(6);
// 我们假设您已经构造了一个用于颜色数据的 `GpuTexture` texture
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(this.texture, OptionalInt.of(0xFFFFFFFF))) {
// 设置管道信息以及任何采样器和统一变量
pass.setPipeline(EXAMPLE_PIPELINE);
pass.setVertexBuffer(0, vertexBuffer);
pass.setIndexBuffer(indexBuffer, indices.type());
pass.bindSampler("Sampler0", RenderSystem.getShaderTexture(0));
// 然后,将所有内容绘制到屏幕
// 在此示例中,缓冲区只包含一个四边形
// 对于那些不知道的人来说,顶点计数为 6,因为四边形由 2 个三角形组成,所以有 2 个顶点重叠
pass.drawIndexed(0, 6);
}
然而,除非您需要如此精细的控制,否则建议在必要时使用带有 MultiBufferSource 的 RenderType,因为它会为您设置大部分内容。
对象引用
大多数用于确定模式和处理纹理的 GL 代码的原始引用已被对象取代。正如 TL;DR 之前提到的,这些通常存储为某种枚举或对象,然后可以解析为其 GL 对应项。一些对象直接包含其引用标识符,例如 BlendFunction。其他对象只是占位符,在适当的位置解析,例如 DepthTestFunction,其枚举值通过 RenderPipeline#toGl 转换。
然而,最大的变化是增加了 GpuTexture。它负责管理与创建、写入和释放写入到某个缓冲区的纹理相关的任何事情。在初始化时,纹理被创建和绑定,并设置任何必要的参数用于 mipmap 和纹理格式。这些 GpuTexture 被存储和引用在任何地方,从 RenderTarget 的深度和颜色目标到支持 TextureAtlas 的纹理。然后,一旦不再需要,纹理通过调用 #close 释放。请注意,尽管技术上可以再次调用 #bind,但纹理已被视为删除,不应再使用。
如果由于某种原因,您需要使用 GpuTexture,实际上使用起来非常简单。首先,您只需通过 GpuDevice#createTexture 构造 GpuTexture。然后,如果您需要更改任何寻址或纹理 mipmap 过滤器,您可以在写入之前随时应用它们。
public class MyTextureManager {
private final GpuTexture texture;
public MyTextureManager() {
this.texture = RenderSystem.getDevice().createTexture(
// 纹理名称,用于日志记录和调试
"Example Texture",
// 纹理像素的格式,可以是三个值之一:
// 值: (纹理内部格式, 纹素数据格式, 纹素数据类型, 像素大小)
// - RGBA8 (GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, 4)
// - RED8 (GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1)
// - DEPTH32 (GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, 4)
TextureFormat.RGBA8,
// 纹理宽度
16,
// 纹理高度
16,
// mipmap 级别和最大细节级别(最小为 1)
1
);
// 设置 UV 分量的纹理模式
// 值:
// - REPEAT (GL_REPEAT)
// - CLAMP_TO_EDGE (GL_CLAMP_TO_EDGE)
this.texture.setAddressMode(
// 用于 U 分量的模式 (GL_TEXTURE_WRAP_S)
AddressMode.CLAMP_TO_EDGE,
// 用于 V 分量的模式 (GL_TEXTURE_WRAP_R)
AddressMode.REPEAT
);
// 设置用于在屏幕上缩放纹理的过滤函数
// 值 (默认, 用于 mipmap):
// - NEAREST (GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR)
// - LINEAR (GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR)
this.texture.setTextureFilter(
// 用于纹理缩小函数的模式 (GL_TEXTURE_MIN_FILTER)
FilterMode.LINEAR,
// 用于纹理放大函数的模式 (GL_TEXTURE_MAG_FILTER)
FilterMode.NEAREST,
// 是否应为缩小函数使用 mipmap(当为 true 时,应具有高于 1 的 mipmap 级别)
false
);
}
}
然后,每当您想要将某些内容上传到纹理时,您可以调用 CommandEncoder#writeToTexture 或 CommandEncoder#copyTextureToTexture。这要么接受要写入的 NativeImage,要么接受带有纹理数据和要使用的 NativeImage$Format 的 IntBuffer。
// 像其他缓冲区/纹理修改方法一样,这必须在渲染通道之外完成
// 我们假设您有一些要加载到纹理中的 `NativeImage` image
RenderSystem.getDevice().createCommandEncoder().writeToTexture(
// 正在写入的纹理(目标)
this.texture,
// 正在读取的图像(源)
image,
// mipmap 级别
0,
// 起始目标 x 偏移
0,
// 起始目标 y 偏移
0,
// 目标宽度(x 大小)
16,
// 目标高度(y 大小)
16,
// 起始源 x 偏移
0,
// 起始源 y 偏移
0
)
最后,当您使用完纹理后,如果它没有被自动处理,不要忘记通过 #close 释放它。
渲染管线
以前,管道是使用 JSON 构造的,其中包含从顶点和片段着色器到其定义的值、采样器和统一变量的所有元数据。然而,这已被一个代码内解决方案取代,该方案将 JSON 的某些部分和原本归入 RenderType 的部分更加本地化。这被称为 RenderPipeline。
可以使用其构建器通过 RenderPipeline#builder 构造 RenderPipeline。然后可以通过调用 build 来构建管道。如果您希望着色器无需任何额外工作即可预编译,则可以将最终的管道传递给 RenderPipeline#register。但是,如果您希望更优雅地处理失败状态,也可以自己处理编译。如果您有跨多个管道使用的代码片段,则可以构建一个部分管道(通过 $Builder#buildSnippet),然后在 builder 方法中将其传递给构造管道。
示例中描述的以下枚举已提供其 GL 代码,因为它们已被抽象化。
// 这假设 RenderPipeline#register 已通过某种形式变为公开
public static final RenderPipeline EXAMPLE_PIPELINE = RenderPipelines.register(
RenderPipeline.builder()
// 管道的名称(必需)
.withLocation(ResourceLocation.fromNamespaceAndPath("examplemod", "pipeline/example"))
// 顶点着色器的位置,相对于 'shaders'(必需)
// 指向 'assets/examplemod/shaders/example.vsh'
.withVertexShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
// 片段着色器的位置,相对于 'shaders'(必需)
// 指向 'assets/examplemod/shaders/example.fsh'
.withFragmentShader(ResourceLocation.fromNamespaceAndPath("examplemod", "example"))
// 着色器内顶点的格式(必需)
.withVertexFormat(
// 顶点格式
DefaultVertexFormat.POSITION_TEX_COLOR,
// 格式的模式
VertexFormat.Mode.QUADS
)
// 添加可以在着色器中引用的常量
// 可以指定名称以及一个 int / float 来表示其值
// 如果未指定值,则应使用 #ifdef / #endif 块进行门控
.withShaderDefines("ALPHA_CUTOUT", 0.5)
// 添加可以在着色器中引用的纹理 sampler2D
// 通常,存储在 `RenderSystem` 中的着色器纹理通过 `Sampler0` - `Sampler11` 引用
// - `Sampler0` 通常总是存在,但这些应该事先设置好
// 此外,对于渲染目标,`InSampler` 通常存在,以及在后处理通道中定义的任何采样器
.withSampler("Sampler0")
// 添加可以在着色器中引用的统一变量
// 这些只是定义,然后根据情况由调用者填充或默认填充
// 默认值可以在 `CompiledShaderProgram#setupUniforms` 中找到
.withUniform("ModelOffset", UniformType.VEC3)
// 自定义统一变量必须手动设置,因为原版批处理系统不支持这样的操作
.withUniform("CustomUniform", UniformType.INT)
// 设置用于在离相机不同距离处渲染对象的深度测试函数
// 值:
// - NO_DEPTH_TEST (GL_ALWAYS)
// - EQUAL_DEPTH_TEST (GL_EQUAL)
// - LEQUAL_DEPTH_TEST (GL_LEQUAL)
// - LESS_DEPTH_TEST (GL_LESS)
// - GREATER_DEPTH_TEST (GL_GREATER)
.withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST)
// 设置多边形应如何渲染
// 值:
// - FILL (GL_FILL)
// - WIREFRAME (GL_LINE)
.withPolygonMode(PolygonMode.FILL)
// 当为 true 时,可以剔除正面或背面的多边形
.withCull(false)
// 指定将两个带有 alpha 的颜色混合在一起时要使用的函数
// 由 `GlStateManager$SourceFactor` 和 `GlStateManager$DestFactor` 组成
// 前两个用于 RGB,后两个用于 alpha
// 如果未指定任何内容,则禁用混合
.withBlend(BlendFunction.TRANSLUCENT)
// 决定是否屏蔽写入颜色和 alpha 到绘制缓冲区
.withColorWrite(
// 屏蔽 RGB
false,
// 屏蔽 alpha
false
)
// 决定是否屏蔽写入值到深度缓冲区
.withDepthWrite(false)
// 决定将 RGBA 颜色应用到帧缓冲区时要应用的逻辑操作
.withColorLogic(LogicOp.NONE)
// 设置用于计算多边形深度值的比例和单位。
// 这取代了多边形偏移。
.withDepthBias(0f, 0f)
.build()
);
从那里,管道可以直接使用,也可以通过某些 RenderType 使用:
// 这将假设 RenderType#create 是公开的
public static final RenderType EXAMPLE_RENDER_TYPE = RenderType.create(
// 渲染类型的名称
"examplemod:example",
// 缓冲区的大小
// 或 4MB
4194304,
// 是否影响应用于方块实体的破碎效果
false,
// 顶点在上传前是否应排序
true,
// 要使用的管道
EXAMPLE_PIPIELINE,
// 要应用的任何其他复合状态设置
RenderType.CompositeState.builder().createCompositeState(RenderType.OutlineProperty.NONE)
);
然后可以通过创建 RenderPass 并将 RenderPipeline 设置为使用您的管道来绘制管道。对于 RenderType,可以使用 MultiBufferSource#getBuffer 获得关联的缓冲区。请注意,不应在 RenderType 中使用自定义统一变量,因为它们不容易设置。
// 由于我们使用的是自定义统一变量,我们必须自己处理
// 我们假设我们有某个 `GpuTexture` texture 要写入
// 创建要使用的渲染通道
try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(
// 要写入的 GPU 颜色纹理
this.texture,
// ARGB 格式的清除颜色
OptionalInt.of(0xFFFFFFFF),
// 深度纹理和清除深度值也可以在此处构造
)
) {
// 添加管道和我们的统一变量
pass.setPipeline(EXAMPLE_PIPELINE);
pass.setUniform("CustomUniform", 1);
// 设置任何其他采样器和要使用的顶点/索引缓冲区
// 最后,调用 draw 函数之一
// 接受要绘制的顶点的第一个索引和索引计数
pass.draw(...);
}
后处理效果
鉴于管道 JSON 已被剥离,这也影响了后处理效果。program 被直接指定 vertex_shader 和 fragment_shader 所取代。此外,统一变量必须指定其 type。
// 1.21.5 之前(对于 'passes' 中的某个 pass)
{
// 与之前相同
"inputs": [ /*...*/ ],
"output": "swap",
// 被 'vertex_shader', 'fragment_shader' 取代
"program": "minecraft:post/box_blur",
"uniforms": [
{
"name": "BlurDir",
// 必需
"values": [ 1.0, 0.0 ]
},
{
"name": "Radius",
// 必需
"values": [ 0.0 ]
}
]
}
// 1.21.5(对于 'passes' 中的某个 pass)
{
// 与之前相同
"inputs": [ /*...*/ ],
"output": "swap",
// 相对于 'shaders'
// 指向 'assets/minecraft/shaders/post/blur.vsh'
"vertex_shader": "minecraft:post/blur",
// 指向 'assets/minecraft/shaders/post/box_blur.fsh'
"fragment_shader": "minecraft:post/box_blur",
"uniforms": [
{
"name": "BlurDir",
// 指定为此统一变量使用的类型
// `Uniform$Type` 之一:
// - int
// - ivec3
// - float
// - vec2
// - vec3
// - vec4
// - matrix4x4
"type": "vec2",
"values": [ 1.0, 0.0 ]
},
{
"name": "Radius",
"type": "float"
// values 不再是必需的
}
]
}
请注意,如果您没有为统一变量定义值,则必须在处理 PostChain 之前在 PostChain#process 的 RenderPass 消费者中通过调用 #setUniform 来指定它们。
// 假设我们已经得到了 `PostChain` post
post.process(Minecraft.getInstance().getMainRenderTarget(), GraphicsResourceAllocator.UNPOOLED, pass -> {
pass.setUniform("Radius", 0.4f);
});
com.mojang.blaze3d.GpuOutOfMemoryException- 当无法在 GPU 上分配纹理时抛出的异常。com.mojang.blaze3d.buffersBufferType不再存储 GL 代码,现在在GlConst#toGl中BufferUsage不再存储 GL 代码,现在在GlConst#toGl中isReadable、isWritable- 返回缓冲区是否可读或可写。
GpuBuffer现在是抽象的- 带有
ByteBuffer的构造函数已移除 size- 返回缓冲区的大小。type- 返回缓冲区的类型。resize、write、read、bind已移除usage- 返回缓冲区的用途。close现在是抽象的isClosed- 返回缓冲区是否已关闭。$ReadView现在是一个接口,定义了缓冲区数据以及如何关闭视图
- 带有
com.mojang.blaze3d.font.SheetGlyphInfo#upload现在接受一个GpuTexturecom.mojang.blaze3d.openglDirectStateAccess- 一个创建数据并将其绑定到某个帧缓冲区的接口。$Core- 一种修改帧缓冲区而不将其绑定到上下文的 DSA 实现。$Emulated- 一种仍然绑定上下文的 DSA 抽象。
GlBuffer- 用于 OpenGL 的GpuBuffer实现。GlCommandEncoder- 用于 OpenGL 的CommandEncoder实现。GlDebugLabel- 用于处理对 GL 指定数据结构的调试引用的标签器。GlDevice- 用于 OpenGL 的GpuDevice实现。GlRenderPass- 用于 OpenGL 的RenderPass实现。GlRenderPipeline- 用于 OpenGL 的CompiledRenderPipeline实现。GlTexture- 用于 OpenGL 的GpuTexture实现。VertexArrayCache- 用于绑定顶点数组并将其上传到 OpenGL 管道的缓存。
com.mojang.blaze3d.pipelineBlendFunction- 一个类,包含在目标中叠加像素时要应用的源和目标颜色及 alpha。这也包含所有原版混合函数。CompiledRenderPipeline- 一个接口,包含具有渲染到屏幕所需所有信息的管道。RenderPipeline- 一个类,包含将某个对象渲染到屏幕所需的一切。它在应用之前类似于渲染状态。RenderTarget现在接受一个表示目标名称的字符串colorTextureId->colorTexture,现在是一个GpuTexture- 同样
getColorTextureId->getColorTexture
- 同样
depthBufferId->depthTexture,现在是一个GpuTexture- 同样
getDepthTextureId->getDepthTexture
- 同样
filterMode现在是一个FilterMode- 同样
setFilterMode用于 int 参数
- 同样
blitAndBlendToScreen不再接受视口大小参数framebufferId已移除checkStatus已移除bindWrite、unbindWrite、setClearColor已移除blitToScreen不再接受任何参数blitAndBlendToScreen->blitAndBlendToTexture,不是一对一clear已移除unbindRead已移除
com.mojang.blaze3d.platformDepthTestFunction- 一个枚举,表示在将样本渲染到帧缓冲区时要应用的受支持深度测试。DisplayData现在是一个记录withSize- 创建一个具有指定宽度/高度的新实例。withFullscreen- 创建一个具有指定全屏标志的新实例。
FramerateLimitTrackergetThrottleReason- 返回游戏帧率被限制的原因。isHeavilyThrottled- 返回当前限制是否显著影响游戏速度。$FramerateThrottleReason- 帧率被限制的原因。
GlConst->com.mojang.blaze3d.opengl.GlConst#toGl- 将某个引用对象映射到其关联的 OpenGL 代码。
GlDebug->com.mojang.blaze3d.opengl.GlDebugenableDebugCallback现在接受一组启用的扩展。
GlStateManager->com.mojang.blaze3d.opengl.GlStateManager_blendFunc、_blendEquation已移除_glUniform2(int, IntBuffer)、_glUniform4(int, IntBuffer)已移除_glUniformMatrix2(int, boolean, FloatBuffer)、_glUniformMatrix3(int, boolean, FloatBuffer)已移除_glUniformMatrix4(int, boolean, FloatBuffer)->_glUniformMatrix4(int, FloatBuffer),transpose 现在始终为 false_glGetAttribLocation已移除_glMapBuffer已移除_glCopyTexSubImage2D已移除_glBindRenderbuffer、_glDeleteRenderbuffers已移除glGenRenderbuffers、_glRenderbufferStorage、_glFramebufferRenderbuffer已移除_texParameter(int, int, float)已移除_genTextures、_deleteTextures已移除_texSubImage2D现在有一个接受IntBuffer而不是long作为像素数据的重载upload已移除_stencilFunc、_stencilMask、_stencilOp、_clearStencil已移除_getTexImage已移除_glDrawPixels、_readPixels已移除$CullState#mode已移除$DestFactor->DestFactor,代码已移除,通过GlConst#toGl调用$FramebufferState枚举已移除$LogicOp->LogicOp,代码已移除,通过GlConst#toGl调用- 除
OR_REVERSE外,所有都已移除 NONE- 不执行逻辑操作。
- 除
$PolygonOffsetState#line已移除$SourceFactor->SourceFactor,代码已移除,通过GlConst#toGl调用$StencilFunc、$StencilState类已移除$Viewport枚举已移除
GlUtil类已移除getVendor、getRenderer、getOpenGlVersion(现在为getVersion)已移至GpuDevice上的实例抽象方法getCpuInfo->GLX#_getCpuInfo
GLXgetOpenGLVersionString已移除_init->_getCpuInfo,不是一对一_renderCrosshair、com.mojang.blaze3d.systems.RenderSystem#renderCrosshair->net.minecraft.client.gui.components.DebugScreenOverlay#render3dCrosshair,不是一对一
PolygonMode- 一个枚举,定义多边形在缓冲区中将如何渲染。NativeImage构造函数现在是公开的upload已移除getPointer- 返回指向图像数据的指针。setPixelABGR现在是公开的applyToAllPixels已移除downloadTexture、downloadDepthBuffer已移除flipY已移除setPackPixelStoreState、setUnpackPixelStoreState已移除$InternalGlFormat枚举已移除$Format不再包含 GL 代码,现在在GlConst#toGl中
TextureUtilgenerateTextureId、releaseTextureId已移除prepareImage已移除writeAsPNG现在接受一个GpuTexture而不是直接的三个整数- 没有
IntUnaryOperator的重载已移除
- 没有
com.mojang.blaze3d.resourceRenderTargetDescriptor现在接受一个表示要清除到的颜色的整数ResourceDescriptorprepare- 在分配后准备资源以供使用。canUsePhysicalResource- 通常返回一个描述符是否已经分配了相同的信息。
com.mojang.blaze3d.shadersAbstractUniform->com.mojang.blaze3d.opengl.AbstractUniformsetSafe方法已移除setMat*方法已移除set(Matrix3f)已移除
CompiledShader->com.mojang.blaze3d.opengl.GlShaderModule$Type->com.mojang.blaze3d.shaders.ShaderType
Uniform->com.mojang.blaze3d.opengl.Uniform- 构造函数现在接受一个
$Type而不是计数和一个表示类型的整数 UT_*字段已移除setFromConfig(ShaderProgramConfig.Uniform)已移除getTypeFromString已移除getType现在返回一个$Typeset(int, float)已移除setSafe现在是私有的$Type- 保存类型名称以及它包含多少个值。getLocation已移除getCount->$Type#countgetIntBuffer、getFloatBuffer已移除$Type->com.mojang.blaze3d.shaders.UniformType
- 构造函数现在接受一个
com.mojang.blaze3d.systemsCommandEncoder- 一个接口,定义如何将各种命令编码到底层渲染系统,例如创建通道、清除和写入纹理,或从缓冲区读取。GpuDevice- 一个接口,定义用于绘制到屏幕的设备或底层渲染系统。它负责创建缓冲区和纹理,同时编译任何管道。RenderPass- 一个接口,定义如何使用底层渲染系统将给定的通道渲染到某个缓冲区。这允许绑定任何采样器并设置所需的统一变量。RenderSystemisOnRenderThreadOrInit、assertOnRenderThreadOrInit已移除recordRenderCall、replayQueue已移除blendFunc、blendFuncSeparate、blendEquation已移除texParameter、deleteTexture、bindTextureForSetup已移除stencilFunc、stencilMask、stencilOp已移除clearDepth已移除glBindBuffer、glBindVertexArray、glBufferData、glDeleteBuffers已移除glUniform1i已移除glUniform1、glUniform2、glUniform3、glUniform4已移除glUniformMatrix2、glUniformMatrix3、glUniformMatrix4已移除setupOverlayColor现在接受一个GpuTexture而不是两个 intbeginInitialization、finishInitialization已移除renderThreadTesselator已移除setShader、clearShader、getShader已移除setShaderTexture现在接受一个GpuTexture而不是一个绑定地址getShaderTexture现在返回一个GpuTexture,如果不存在则返回 nullpixelStore、readPixels已移除queueFencedTask、executePendingTasks- 处理发送在 GPU 上异步运行的任务。SCISSOR_STATE- 保存主要的剪裁状态。disableDepthTest、enableDepthTest已移除depthFunc、depthMask已移除enableBlend、disableBlend已移除neableCull、disableCull已移除polygonMode、enablePolygonOffset、disablePolygonOffset、polygonOffset已移除enableColorLogicOp、disableColorLogicOp、logicOp已移除bindTexture、viewport已移除colorMask、clearColor、clear已移除setupShaderLights(CompiledShaderProgram)已移除getShaderLights- 返回表示块光和天空光的向量。drawElements、getString已移除initRenderer现在接受窗口指针、默认着色器源以及一个是否使用调试标签的布尔值setupDefaultState不再接受任何参数maxSupportTextureSize已移除glDeleteVertexArrays已移除defaultBlendFunc已移除setShaderTexture已移除getQuadVertexBuffer- 返回一个绑定了一个四边形的顶点缓冲区。getDevice、tryGetDevice- 返回表示要使用的底层渲染系统的GpuDevice。getCapsString已移除activeTexture已移除setModelOffset、resetModelOffset、getModelOffset- 处理在渲染模型时应用于ModelOffset统一变量的偏移量。通常用于云和世界边界。$AutoStorageIndexBuffer#bind->getBuffer,不是一对一$GpuAsyncTask- 一个保存回调和围栏对象的记录,用于将信息同步到 GPU。
ScissorState- 一个类,保存要渲染的屏幕部分。
com.mojang.blaze3d.texturesAddressMode- 设置为如何将纹理渲染到特定位置的模式。FilterMode- 设置为当细节级别函数确定纹理应如何最大化或最小化时如何渲染纹理的模式。GpuTexture- 根据需要绑定和写入 GPU 的纹理。TextureFormat- 指定纹理应分配的格式。
com.mojang.blaze3d.vertexPoseStackmulPose(Quaternionf)、rotateAround现在接受Quaternionfc而不是Quaternionfclear->isEmptymulPose(Matrix4f)->mulPose(Matrix4fc)$PosecomputeNormalMatrix现在是私有的transformNormal现在接受Vector3fc作为其第一个参数translate、scale、rotate、rotateAround、setIdentity、mulPose现在除了在堆栈上之外,在姿势本身上也可用
VertexBuffer->com.mojang.blaze3d.buffers.GpuBuffer,不是一对一- 一些逻辑也移至
VertexFormat
- 一些逻辑也移至
VertexFormatbindAttributes已移除setupBufferState、clearBufferState、getImmediateDrawVertexBuffer->uploadImmediateVertexBuffer、uploadImmediateIndexBuffer;不是一对一$IndexType不再存储 GL 代码,现在在GlConst#toGl中$Mode不再存储 GL 代码,现在在GlConst#toGl中
VertexFormatElementsetupBufferState已移除$Type不再存储 GL 代码,现在在GlConst#toGl中$Usage不再存储 GL 函数调用,现在在VertexArrayCache#setupCombinedAttributes中
com.mojang.mathMatrixUtilisIdentity、isPureTranslation、isOrthonormal现在接受一个Matrix4fccheckProperty- 检查提供的属性是否在矩阵中表示。
OctahedralGrouptransformation现在返回一个Matrix3fcfromAnges->fromXYAngles,不是一对一
Quadrant- 一个包含 90 度增量旋转的枚举。SymmetricGroup3#transformation现在返回一个Matrix3fcTransformation现在接受一个Matrix4fcgetMatrix现在返回一个Matrix4fcgetMatrixCopy- 返回当前矩阵的深拷贝。
net.minecraft.client.gui.font.FontTexture现在接受一个提供的标签字符串net.minecraft.client.main.GameConfig现在接受一个布尔值,表示是否渲染调试标签net.minecraft.client.rendererCloudRenderer#render不再接受用于投影或姿势的Matrix4fCompiledShaderProgram->com.mojang.blaze3d.opengl.GlProgramlink现在接受一个字符串作为着色器名称setupUniforms现在接受$UniformDescription列表以及采样器使用的名称列表getUniformConfig已移除bindSampler现在接受一个GpuTexture而不是整数绑定标识符parseUniformNode已移除
CoreShaders->RenderPipelines,不是一对一LightTexture#getTarget- 返回包含基于玩家的当前等级的光照纹理的GpuTexture。PostChainload不再接受ShaderManager,现在接受一个表示链名称的ResourceLocationaddToFrame、process现在接受一个RenderPass消费者,用于将任何其他设置应用于要渲染的通道setUniform已移除setOnRenderPass- 在RenderPass上的后处理链中设置统一变量,以供着色器使用。
PostChainConfig$Pass现在接受顶点和片段着色器的 id,而不是程序 idreferencedTargets- 返回通道中引用的要应用的目标。program已移除
$Uniform现在接受统一变量的类型以及一个可选的浮点数列表(如果值不需要被覆盖)
PostPass不再接受CompiledShaderProgram,现在接受RenderPipeline而不是表示通道名称的字符串addToFrame现在接受一个RenderPass消费者,用于将任何其他设置应用于要渲染的通道getShader已移除$Input#bindTo现在接受RenderPass而不是CompiledShaderProgram
RenderStateShard- 使用多边形偏移的
$LayerStateShard已移除 getName- 返回着色器的名称。$TransparencyStateShard类已移除- 现在通过
BlendFunction处理
- 现在通过
$ShaderStateShard类已移除- 由
VertexBuffer直接引用
- 由
$CullStateShard类已移除- 现在作为
RenderPipeline上的设置处理
- 现在作为
$DepthTestStateShard类已移除- 现在通过
DepthTestFunction处理
- 现在通过
$WriteMaskStateShard类已移除- 现在作为
RenderPipeline上的设置处理
- 现在作为
$ColorLogicStateShard类已移除- 现在作为
RenderPipeline上的设置处理
- 现在作为
$OutputStateShard现在接受一个提供的RenderTarget而不是用于启动和拆除状态的 runnable
- 使用多边形偏移的
RenderType不再接受VertexFormat或VertexFormat$ModeSKY、END_SKY、sky、endSky、stars已移除ENTITY_OUTLINE_BLIT、entityOutlineBlit已移除PANORAMA、panorama已移除CREATE_LIGHTMAP、createLightmap已移除createClouds、flatClouds、clouds、cloudsDepthOnly已移除worldBorder已移除debugLine- 返回与调试线关联的RenderType。entityOutlineBlit- 返回用于渲染实体轮廓的RenderType。panorama- 返回用于渲染全景模式的RenderType。createLightmap- 返回用于渲染光照图纹理的RenderType。create不再接受VertexFormat或VertexFormat$Mode,而是接受RenderPipelinegetRenderTarget、getRenderPipeline- 返回用于渲染的目标和管道。format、mode、draw现在是抽象的$CompositeStateBuilder方法现在是 protected$OutlineProperty现在是 protected
ShaderDefines$Builder#define现在有一个接受整数的重载ShaderManagerSHADER_INCLUDE_PATH现在是私有的MAX_LOG_LENGTH已移除preloadForStartup已移除,被GpuDevice#precompilePipeline取代getProgram、getProgramForLoading->getShader,不是一对一linkProgram现在接受RenderPipeline而不是ShaderProgram和ShaderProgramConfig$CompilationCache#getOrCompileProgram、getOrCompileShader->getShaderSource,不是一对一$Configs不再接受程序映射$ShaderCompilationKey记录已移除
ShaderProgram、ShaderProgramConfig->RenderPipeline,不是一对一SkyRenderer#renderDarkDisc不再接受PoseStack
net.minecraft.client.renderer.chunk.SectionRenderDispatcheruploadSectionLayer、uploadSectionIndexBuffer->$RenderSection#uploadSectionLayer、uploadSectionIndexBuffer$SectionBuffers- 一个保存用于渲染部分的缓冲区的类。
net.minecraft.client.renderer.textureAbstractTextureNOT_ASSIGNED已移除texture、getTexture- 保存要渲染的纹理的引用。getId、releaseId已移除bind已移除
DynamicTexture现在接受纹理的标签SpriteContents#uploadFirstFrame、$AnimatedTexture#uploadFirstFrame现在接受一个GpuTextureSpriteTicker#tickAndUpload现在接受GpuTextureTextureAtlasSprite#uploadFirstFrame、$Ticker#tickAndUpload现在接受GpuTexture
模型重做
模型系统已进一步分离为用于方块状态、方块和物品的模型。因此,统一的 BakedModel 已被完全移除,并分离到它们自己的部分中,分三步加载:从 JSON 加载、解析依赖关系,然后烘焙以供关联的方块状态模型或物品模型使用。作为参考,下面讨论的所有内容都是在 ModelManager#reload 中并行发生的。
首先,让我们从方块和物品之间使用的基础模型 JSON 开始。这些被加载到 UnbakedModel(具体来说是 BlockModel)中,其中包含熟悉的属性,例如 gui 光照和纹理槽位。然而,一个变化是将元素与其渲染设置分离。这些持有渲染四边形的元素存储在 UnbakedGeometry 中。UnbakedGeometry 负责将模型烘焙成 QuadCollection,它实际上保存了要渲染的 BakedQuad 列表。目前,原版只有 SimpleUnbakedGeometry,它保存了熟悉的 BlockElement 列表。这些 UnbakedModel 一旦加载,就会被传递给 ModelDiscovery 以解析方块状态和物品模型。
接下来是 ResolvableModel,它是方块状态和物品模型的基础。这些模型本质上作为标记,请求它们将使用的 UnbakedModel。然后,我们有它们的子类型 BlockStateModel$UnbakedRoot(用于方块状态 JSON)和 ItemModel$Unbaked(用于客户端物品 JSON 中引用的模型)。每个都以某种方式实现 resolveDependencies,以调用 ResolvableModel$Resolver#markDependency,传入它们想要使用的模型位置。
从技术上讲,
BlockStateModel更复杂一些,因为变体在加载期间使用BlockStateModel$Unbaked,然后在初始化期间转换为$UnbakedRoot。
现在我们知道了应该加载哪些模型,它们必须被放入一个可用于烘焙的状态。这是 ModelDiscovery 的工作,它接受一个 ResolvableModel,并在第一次引用时将 UnbakedModel 加载到 ResolvedModel 中。顾名思义,ResolvedModel 是围绕 UnbakedModel 的功能包装器,用于解析所有依赖链。
从那里,为 BlockState 构建模型组,并加载纹理,从而进入实际烘焙 BlockStateModel 和 ItemModel 的最后一步。这通过 $UnbakedRoot(或 $Unbaked)和 ModelBakery 上提供的 bake 方法处理。简而言之,bake 构建 BakedQuad 列表,其中包含方块状态或物品模型本身所需的任何其他信息。ResolvedModel 从烘焙器中获得,然后调用其实例方法。对于 BlockStateModel,这通过 SimpleModelWrapper#bake 解析,从中从 Variant 数据获得 ModelState。它们将烘焙的四边形存储在 BlockModelPart 中。对于 ItemModel,它直接使用 BakedQuad 列表以及由 ModelRenderProperties#fromResolvedModel 提供的信息。这确实意味着每个 BlockStateModel 和 ItemModel 如果同一个模型在多个位置被引用,则可能包含重复(但唯一)的 BakedQuad。
方块生成器:变体修改器
鉴于所有分离出方块状态 JSON 加载的变化,BlockModelGenerators 也有许多变化。虽然其中大部分只是重命名(例如,BlockStateGenerator -> BlockModelDefinitionGenerator),但主要变化是增加了 VariantMutator。VariantMutator 在功能上是 Variant 上的一元运算符,用于设置某些设置。这一增加简化了(或者说更像是编解码器构造)PropertyDispatch 的使用,以便更快速地根据其属性分派具有变体的方块。
// 在水平朝向属性上创建一个属性分派
// 应用关联的变体,但如果需要,也可以提供一个函数式接口
public static final PropertyDispatch<VariantMutator> ROTATION_HORIZONTAL_FACING = PropertyDispatch.modify(BlockStateProperties.HORIZONTAL_FACING)
.select(Direction.EAST, BlockModelGenerators.Y_ROT_90)
.select(Direction.SOUTH, BlockModelGenerators.Y_ROT_180)
.select(Direction.WEST, BlockModelGenerators.Y_ROT_270)
.select(Direction.NORTH, BlockModelGenerators.NOP);
// 然后,在可以访问 `Consumer<BlockModelDefinitionGenerator>` blockStateOutput 的地方
this.blockStateOutput.accept(
MultiVariantGenerator.dispatch(EXAMPLE_BLOCK).with(ROTATION_HORIZONTAL_FACING)
);
net.minecraft.client.data.modelsBlockModelGeneratorsnonOrientableTrapdoor->NON_ORIENTABLE_TRAPDOOR,现在是静态的- 常量现在可用于常见的
VariantMutator,例如将方块模型旋转一定角度 texturedModels->TEXTURED_MODELS,现在是静态的MULTIFACE_GENERATOR现在是私有的plainModel- 从模型位置创建一个变体。variant、variants- 从一些Variant创建一个常规的MultiVariantplainVariant- 从其位置创建一个只有一个模型的MultiVariant。condition- 为多部分模型创建一个新的条件构建器or- 对多个条件进行 OR 操作。- 大多数生成器方法现在返回
BlockModelDefinitionGenerator、Variant或MultiVariant,并接受一个Variant或MultiVariant而不是指向所需模型的ResourceLocationVariantProperties已被VariantMutator取代Condition$TerminalCondition被Condition取代
createHorizontalFacingDispatch、createHorizontalFacingDispatchAlt、createTorchHorizontalDispatch已移除createFacingDispatch已移除createRotatedVariant(Block, ResourceLocation)已移除selectMultifaceProperties- 基于提供的BlockState和方向到属性函数,创建一个属性到VariantMutator的映射。applyRotation不再接受Variant,并返回一个VariantMutator
ItemModelGenerators#generateSpawnEgg已移除ModelProvider#saveAll已移除
net.minecraft.client.data.models.blockstatesBlockStateGenerator->BlockModelDefinitionGenerator,不是一对一Condition->net.minecraft.client.renderer.block.model.multipart.Condition,不是一对一validate->instantiate,不是一对一
ConditionBuilder- 使用属性值构建一个条件MultiPartGenerator现在实现BlockModelDefinitionGeneratorwith(List<Variant>)->with(MultiVariant)with(Variant)已移除with(Condition, ...)->with(Condition, MultiVariant)- 接受
ConditionBuilder的重载
- 接受
$ConditionalEntry、$Entry已移除
MultiVariantGenerator现在实现BlockModelDefinitionGeneratormultiVariant->dispatchmultiVariant(Block, ...)->dispatch(Block, MultiVariant)$Empty- 一个匹配每个方块状态的多变体条目。
PropertyDispatch有一个包含分派值的泛型- 泛型
V替换了所有List<Variant>的值 property、properties->initial或modify$C*#generateList方法已移除$*Function已移除
- 泛型
Selector->PropertyValueList,不是一对一Variant->net.minecraft.client.renderer.block.model.Variant,不是一对一VariantProperties->net.minecraft.client.renderer.block.model.VariantMutator,不是一对一VariantProperty->net.minecraft.client.renderer.block.model.VariantMutator$VariantProperty,不是一对一
net.minecraft.client.renderer.ItemInHandRenderer#renderItem不再接受表示物品是否在左手中的布尔值net.minecraft.client.renderer.blockBlockModelShaper#stateToModelLocation、statePropertiesToString已移除BlockRenderDispatcher#renderBatched现在接受一个BlockModelPart列表而不是RandomSourceModelBlockRenderertesselateBlock、tesselateWithAO、tesselateWithoutAO不再接受RandomSource,并将BlockStateModel替换为BlockModelPart列表renderModel现在是静态的,不再接受BlockState$AmbientOcclusionFace->$AmbientOcclusionRenderStorage$CommonRenderStorage- 一个类,保存用于在其给定位置渲染方块的一些元数据。$SizeInfo现在接受直接索引,而不是从其方向和翻转布尔值计算信息
net.minecraft.client.renderer.block.modelBakedQuad现在是一个记录BlockElement现在是一个记录from、to现在是Vector3fc
BlockElementFace现在接受一个Quadrant作为面旋转getU、getV- 返回旋转后的纹理坐标。$Deserializer#getTintIndex现在是私有的和静态的
BlockFaceUV->BlockElementFace$UVs,不是一对一BlockModel现在是一个记录,接受一个UnbakedGeometry而不是直接的BlockElement列表$Deserializer#getElements现在返回一个UnbakedGeometry
BlockModelDefinition现在是一个记录,接受$SimpleModelSelectors和$MultiPartDefinitionGSON、fromStream、fromJsonElement->CODEC,不是一对一instantiate现在接受一个提供的字符串而不是直接的字符串$Deserializer已移除$MultiPartDefinition- 一个记录,保存用于获取多部分模型的选择器列表。$SimpleModelSelectors- 一个记录,保存变体到其未烘焙模型实例的映射。
BlockModelPart- 方块的烘焙模型表示。BlockStateModel- 方块状态的烘焙表示。collectParts- 获取用于渲染此状态的烘焙模型列表。$SimpleCachedUnbakedRoot- 一个类,表示某个$Unbaked模型的委托。$Unbaked- 一个可以创建$SimpleCachedUnbakedRoot的$UnbakedRoot的扩展
FaceBakerybakeQuad现在接受Vector3fc而不是Vector3frecomputeUVs已移除extractPositions- 提取面的位置并将它们传递给一个消费者以供使用。
ItemTransform现在是一个记录,向量是Vector3fcMultiVariant->net.minecraft.client.data.models.MultiVariantCODECwith- 创建一个带有指定修改器的MultiVariant。$Deserializer类已移除
SimpleModelWrapper现在实现BlockModelPartSimpleUnbakedGeometry- 一个保存要烘焙的BlockElement列表的未烘焙几何体。SingleVariant- 一个BlockStateModel实现,其状态只有一个模型。UnbakedBlockStateModel->BlockStateModel$UnbakedRootVariant不再实现ModelState,现在接受$SimpleModelState而不是直接的旋转和 uv 锁定- 构造函数现在有一个只提供
ResourceLocation的重载,不再接受权重,将其留给MultiVariant CODECwithXRot、withYRot、withUvLock、withModel、withState、with- 将变体变异为一个应用了给定设置的新对象。$Deserializer类已移除$SimpleModelState- 一个记录,保存 x/y 旋转和 uv 锁定。
- 构造函数现在有一个只提供
VariantMutator- 一个变体上的一元运算符,将指定设置应用于变体。在状态生成期间使用。
net.minecraft.client.renderer.block.model.multipartAndCondition、OrCondition->CombinedCondition,不是一对一KeyValueCondition现在是一个记录,接受一个要测试的键到术语的映射MultiPart->MultiPartModel$Unbaked$DefinitionCODECgetMultiVariants已移除
$Deserializer类已移除
Selector现在是一个记录,接受一个BlockStateModel$Unbaked而不是MultiVariant$Deserializer类已移除
net.minecraft.client.renderer.entity.ItemRendererrenderItem现在接受一个List<BakedQuad>而不是BakedModelrenderStatic不再接受一个表示物品握在哪只手中的布尔值
net.minecraft.client.renderer.itemBlockModelWrapper现在有一个公共构造函数,接受染色源列表、四边形列表和ModelRenderProperties- 四边形列表和
ModelRenderProperties取代了直接的BakedModel,或者现在的BlockStateModel computeExtents- 将烘焙四边形的顶点提取到一个数组中。
- 四边形列表和
ItemModel$BakingContext#bake已移除ItemModelResolver#updateForLiving、updateForTopItem不再接受表示物品是否在左手中的布尔值ItemStackReenderStateisGui3d已移除transform已移除visitExtents- 访问模型要渲染的所有顶点,并将它们传递给提供的消费者。$LayerRenderStateNO_EXTENTS_SUPPLIER- 一个空的顶点列表。setupBlockModel已被拆分为prepareQuadList、setRenderType、setUsesBlockLight、setExtents、setParticleIcon、setTransformsetupSpecialModel不再接受基础BakedModel
MissingItemModel现在接受一个BakedQuad列表和ModelRenderProperties,而不是直接的BakedModelModelRenderProperties- 用于渲染模型的属性,通常从ResolvedModel检索。SpecialModelRenderer现在接受ModelRenderProperties而不是基础BakedModel
net.minecraft.client.resources.modelBakedModel->net.minecraft.client.resources.model.QuadCollection,不是一对一BlockModelRotationby现在接受Quadrant而不是整数withUvLock- 返回带有旋转和声明锁定 UV 用于旋转的模型状态。
BlockStateDefinitions- 一个用于创建方块名称到其状态定义映射的管理器。BlockStateModelLoaderModelResourceLocation字段已移除loadBlockState不再接受缺失模型$LoadedModel类已移除$LoadedModels现在接受一个BlockStateModel$UnbakedRoot而不是$UnbakedforResolving、plainModels已移除
DelegateBakedModel->net.minecraft.client.renderer.block.model.SimpleModelWrapper,不是一对一MissingBlockModel#VARIANT已移除ModelBakerbake->getModel,不是一对一- 烘焙器只是检索
ResolvedModel
- 烘焙器只是检索
rootName已移除compute- 计算包含ModelBaker的提供的键。通常用于烘焙BlockStateModel$SharedOperationKey- 一个接口,通常计算未烘焙模型的某个烘焙过程。
ModelBakery现在接受一个Map<BlockState, BlockStateModel$UnbakedRoot>用于未烘焙的方块状态模型,一个Map<ResourceLocation, ResolvedModel>用于加载的模型,以及一个ResolvedModel用于缺失模型bakeModels现在接受一个SpriteGetter和一个Executor,同时返回一个CompletableFuture用于并行加载和烘焙$BakingResult现在接受一个$MissingModels用于缺失的方块状态和物品模型,以及一个Map<BlockState, BlockStateModel>用于烘焙的方块状态模型;缺失的物品模型存储在$MissingModels中$MissingModels- 保存方块状态和物品的缺失模型。$TextureGetter接口已移除
ModelDebugName不再继承Supplier<String>,而是使用debugNameModelDiscoveryregisterSpecialModels已移除discoverDependencies现在是私有的getReferencedModels、getUnreferencedModels已移除addSpecialModel- 将一个根模型添加到任意加载的模型列表中。missingModel- 返回缺失模型resolve- 解析所有模型依赖关系,返回模型名称到其模型的映射。
ModelGroupCollector$GroupKey#create现在接受一个BlockStateModel$UnbakedRoot而不是$UnbakedModelManagergetModel已移除getMissingModel->getMissingBlockStateModel$ResolvedModels- 一个包含已解析依赖关系的模型的映射。
ModelResourceLocation记录已移除ModelStategetRotation->transformationisUvLocked已移除faceTransfomration、inverseFaceTransformation- 处理返回用于烘焙面顶点的变换后的Matrix4fc。
MultiPartBakedModel->net.minecraft.client.renderer.block.model.multipart.MultiPartModel- 现在实现
BlockStateModel而不是继承DelegateBakedModel $SharedBlockState- 一个持有者,包含映射到其$Selector的BlockStateModel。
- 现在实现
QuadCollection- 一个包含要基于关联方向和剔除渲染的四边形列表的数据对象。ResolvableModel$Resolver#resolve->markDependency,不是一对一- 不再直接解析,而是标记依赖关系以供后续后处理步骤使用
ResolvedModel- 一个UnbakedModel,其模型和纹理依赖关系已被完全解析。SimpleBakedModel->net.minecraft.client.renderer.block.model.SimpleModelWrapper或net.minecraft.client.renderer.block.model.SimpleUnbakedGeometry,不是一对一SpriteGetterget、reportMissingReference现在接受ModelDebugNameresolveSlot- 将TextureSlot中的键解析为其TextureAtlasSprite。
UnbakedGeometry- 一个接口,构造在烘焙时要渲染的四边形集合。UnbakedModel不再实现ResolvableModelDEFAULT_AMBIENT_OCCLUSION、DEFAULT_GUI_LIGHT已移除PARTICLE_TEXTURE_REFERENCE- 保存表示粒子纹理的键。bake已移除getAmbientOcclusion->ambientOcclusiongetGuiLight->guiLightgetTransforms-transformsgetTextureSlots-textureSlotsgeometry- 保存表示模型元素的未烘焙几何体。getParent->parent,不是一对一bakeWithTopModelValues已移除getTopTextureSlots、getTopAmbientOcclusion、getTopGuiLight、getTopTransform、getTopTransforms已移除
WeightedBakedModel->WeightedVariants- 现在实现
BlockStateModel而不是继承DelegateBakedModel
- 现在实现
net.minecraft.world.item.ItemDisplayContext#leftHand- 返回显示上下文是否正在使用实体的左手渲染。
小幅迁移
以下是有用或有趣的增加、变更和移除的列表,它们不值得在入门文档中拥有自己的章节。
实体引用
通常,存储另一个实体的 UUID 是为了稍后获取该实体以执行某些逻辑。然而,如果实体在某个时间点被移除,存储原始实体可能会导致问题。因此,添加了 EntityReference 来处理从 UUID 解析实体,同时确保在查询时它仍然存在。
EntityReference 只是一个包装的 Either,要么持有实体实例,要么持有 UUID。当通过 getEntity 解析时,它将尝试验证存储的实体(如果存在)是否未被移除。如果被移除,它将获取 UUID 以再次查找实体本身。如果该实体确实存在,则返回它,否则返回 null。
实体中对 UUID 的大多数引用已被替换为 EntityReference 以促进此更改。
net.minecraft.network.syncher.EntityDataSerializers#OPTIONAL_UUID->OPTIONAL_LIVING_ENTITY_REFERENCE,不是一对一,因为它可以持有实体引用net.minecraft.server.level.ServerLevel#getEntity(UUID)->Level#getEntity(UUID)net.minecraft.world.entityEntityReference- 一个对实体的引用,要么通过其在世界中的实体实例,要么通过 UUID。LivingEntity#lastHurtByPlayer、lastHurtByMob现在是EntityReferenceOwnableEntitygetOwnerUUID->getOwnerReference,不是一对一level现在返回一个Level而不是EntityGetter
TamableAnimal#setOwnerUUID->setOwner或setOwnerReference;不是一对一
net.minecraft.world.entity.animal.horse.AbstractHorse#setOwnerUUID->setOwner,不是一对一net.minecraft.world.level.Level现在实现UUIDLookup<Entity>net.minecraft.world.level.entityEntityAccess现在实现UniquelyIdentifyableUniquelyIdentifyable- 一个声称对象具有 UUID 并跟踪对象是否被移除的接口。UUIDLookup- 一个通过 UUID 查找类型的接口。
解作用域玩家参数
许多接受 Player 的方法已被解作用域,根据用例接受 LivingEntity 或 Entity。以下方法是此情况的非详尽列表。
net.minecraft.world.entity.EntityTypespawncreateDefaultStackConfig、appendDefaultStackConfigappendCustomEntityStackConfig、updateCustomEntityTag
net.minecraft.world.itemBucketItem#playEmptySoundDispensibleContainerItem#checkExtraContent、emptyContents
net.minecraft.world.levelLevelplaySeededSoundmayInteract
LevelAccessorplaySoundlevelEvent
net.minecraft.world.level.blockBucketPickup#pickupBlockLiquidBlockContainer#canPlaceLiquid
net.minecraft.world.level.block.entity.BrushableBlockEntity#brush
组件交互事件
MutableComponent 上的点击和悬停事件已被重做为类似 MapCodec 注册表的系统。它们现在都是接口,将其编解码器注册到一个 $Action 枚举。然后,该实现创建一个引用 $Action 类型的编解码器,并存储逻辑应用所需的任何必要信息。然而,没有与组件交互关联的直接“动作”逻辑。相反,它们被硬编码到它们的使用位置。对于点击事件,是在 Screen#handleComponentClicked 中。对于悬停事件,是在 GuiGraphics#renderComponentHoverEffect 中。因此,任何添加的额外事件都需要注入到枚举以及这两个位置之一或两者中。
net.minecraft.network.chatClickEvent现在是一个接口getAction->actiongetValue现在根据需要在其子类上,用于其各自的类型
HoverEvent现在是一个接口getAction->action$EntityTooltipInfoCODEC现在是一个MapCodeclegacyCreate已移除
$ItemStackInfo已移除,被$ShowItem取代$LegacyConverter接口已移除
纹理图集重做
纹理图集逻辑已最终确定为一个注册表编解码器系统;然而,图集数据的查询方式已更改。首先,所有图集标识符存储在 AtlasIds 中,而相应的纹理位置存储在 Sheets 中。要从图集中获取材质,使用 MaterialMapper 作为纹理位置和要附加到材质的关联前缀的包装器。然后可以通过 apply 传入您想要使用的材质的 id 来获得 Material。
例如:
// 在 sheets 中找到
public static final MaterialMapper ITEMS_MAPPER = new MaterialMapper(TextureAtlas.LOCATION_BLOCKS, "item");
public static final MaterialMapper BLOCKS_MAPPER = new MaterialMapper(TextureAtlas.LOCATION_BLOCKS, "block");
// 查找位于 `assets/examplemod/textures/item/example_item.png` 的纹理的材质
public static final Material EXAMPLE_ITEM = ITEMS_MAPPER.apply(ResourceLocation.fromNamespaceAndPath("examplemod", "example_item"));
// 查找位于 `assets/examplemod/textures/block/example/block.png` 的纹理的材质
public static final Material EXAMPLE_BLOCK = ITEMS_MAPPER.apply(ResourceLocation.fromNamespaceAndPath("examplemod", "example/block"));
net.minecraft.client.data.AtlasProvider- 用于生成纹理图集提供者的数据提供者。net.minecraft.client.data.models.ItemModelGeneratorsSLOT_*->TRIM_PREFIX_*,现在是公开的,并且是ResourceLocationTRIM_MATERIAL_MODELS现在是公开的generateTrimmableItem现在接受ResourceLocation而不是String$TrimMaterialData现在是公开的,接受MaterialAssetGroup而不是名称和覆盖材质
net.minecraft.client.rendererMaterialMapper- 一个存储图集纹理位置和应用于纹理中 id 的前缀的对象。Sheets*_MAPPER- 每个纹理图集纹理的MaterialMapper。createBedMaterial(ResourceLocation)已移除createShulkerMaterial(ResourceLocation)已移除createSignMaterial(ResourceLocation)已移除chestMaterial(String)、chestMaterial(ResourceLocation)已移除createDecoratedPotMaterial(ResourceLocation)已移除
net.minecraft.client.renderer.blockentity.ConduitRenderer#MAPPER- 一个从方块图集获取潮涌核心纹理的映射器。net.minecraft.client.renderer.texture.atlasSpriteSource#type->codec,不是一对一SpriteSources现在包含类似于客户端注册表的逻辑,通过其 id 映射器SpriteSourceType记录已移除
net.minecraft.client.renderer.texture.atlas.sourcesDirectoryLister现在是一个记录PalettedPermutations现在是一个记录SingleFile现在是一个记录SourceFilter现在是一个记录Unstitcher现在是一个记录$Region现在是公开的
net.minecraft.client.resources.model.AtlasIds- 一个保存所有原版纹理图集的ResourceLocation的类。
注册表上下文交换器
客户端物品现在存储一个 RegistryContextSwapper,用于正确检查访问注册表对象的客户端物品信息。在等级加载之前,它会获得一个占位符以避免崩溃,并在渲染期间用正确的值填充。
net.minecraft.client.multiplayerCacheSlot- 一个包含从某个上下文计算出的值的对象。更新时,先前的值被覆盖,上下文注册该槽位以进行清理。ClientLevel现在实现CacheSlot$Cleaner
net.minecraft.client.renderer.itemClientItem现在可以接受一个可为 null 的RegistryContextSwapperwithRegistrySwapper- 在ClientItem中设置RegistryContextSwapper
ItemModel$BakingContext现在接受一个RegistryContextSwapper
net.minecraft.utilPlaceholderLookupProvider- 一个包含引用对象的占位符的提供者。在客户端物品中使用,因为它们将在RegistyAccess填充之前加载。RegistryContextSwapper- 一个用于将某个对象换成另一个不同对象的接口。由客户端物品用于将占位符换成加载的RegistryAccess。
重载实例创建
重载实例已被稍微重新排列。SimpleReloadInstance 基础现在只接受 List<PreparableReloadListener>,其他字段被传入 of 函数,以便可以立即调用 #startTasks。
net.minecraft.server.packs.resourcesProfiledReloadInstance构造函数现在是私有的,通过of访问SimpleReloadInstance只接受List<PreparableReloadListener>of现在返回一个ReloadInstance,不是一对一allPreparations现在是包私有的allDone现在是私有的startTasks- 开始重载监听器。prepareTasks- 运行执行器并设置读取和加载所有所需数据所需的 future。StateFactory$SIMPLE- 一个调用PreparableReloadListener#reload的工厂
方块效果应用器
当实体在方块内部时应用于实体的效果现在通过 InsideBlockEffectApplier 和 InsideBlockEffectType 处理。InsideBlockEffectType 是一个枚举,包含一个消费者,用于在调用时应用到实体上。另一方面,InsideBlockEffectApplier 存储在实体上,作为一种基于枚举序数以有序方式应用效果的方法。
要调用其中一种效果类型,您必须覆盖 BlockBehaviour#entityInside 或 Fluid#entityInside 并调用 InsideBlockEffectApplier#apply。如果某些内容应在效果类型之前应用,例如在细雪中冻结之前灭火,则应在 apply 之前调用 InsideBlockEffectApplier#runBefore。类似地,如果某些内容应在之后运行,例如在被放入熔岩后伤害敌人,则应调用 runAfter。
// 在某个方块或流体子类中
@Override
protected void entityInside(Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier applier) {
applier.runBefore(InsideBlockEffectType.EXTINGUISH, entity -> {
// 在此处修改实体。
});
// 执行存储在类型上的基本应用逻辑
applier.apply(InsideBlockEffectType.FIRE_IGNITE);
applier.runAfter(InsideBlockEffectType.FIRE_IGNITE, entity -> {
// 执行由于效果应用而产生的任何最终检查
entity.hurt(...);
});
}
net.minecraft.world.entityInsideBlockEffectApplier- 一个接口,定义实体在给定方块内时应如何交互。InsideBlockEffectType- 一个枚举,定义当在引用该类型的特定方块内部时要执行的行为。
net.minecraft.world.level.block.state.BlockBehaviour#entityInside、$BlockStateBase#entityInside现在接受一个InsideBlockEffectAppliernet.minecraft.world.level.material.Fluid#entityInside、FluidState#entityInside- 每当实体被认为在流体的边界框内时调用的方法。
定时器回调,加入编解码器俱乐部!
用于在服务器计划中执行事件的 TimerCallback,通常是数据包中的 mcfunctions,现在已被重做为编解码器形式。这意味着可以通过将 MapCodec 传递给 TimerCallbacks#register(通过 TimerCallbacks#SERVER_CALLBACKS)而不是序列化器,将回调注册到可用回调列表中。
net.minecraft.world.level.timersFunctionCallback现在是一个记录FunctionTagCallback现在是一个记录TimerCallbackcodec- 返回用于序列化的编解码器。$Serializer类已移除
TimerCallbacksserialize、deserialize->codec,不是一对一
JOML 后端接口
Mojang 选择通过传递其逻辑对象的实现接口(通常附加一个 c)来减少对 JOML 对象的限制。例如,Vector3f 变成 Vector3fc,Matrix4f 变成 Matrix4fc。这不会改变任何逻辑本身,因为 c 接口由类组件实现。
标签变更
minecraft:worldgen/biomespawns_cold_variant_farm_animalsspawns_warm_variant_farm_animals
minecraft:blocksword_instantly_minesreplaceable_by_mushroomsplays_ambient_desert_block_soundsedible_for_sheepdead_bush_may_place_on->dry_vegetation_may_place_oncamels_spawnable_on
minecraft:cat_variant已移除minecraft:entity_typecan_equip_saddlecan_wear_horse_armor
minecraft:itembook_cloning_targeteggsflowers
状态效果字段重命名
一些状态效果已重命名为其游戏内名称,而不是某些内部描述符。
MOVEMENT_SPEED->SPEEDMOVEMENT_SLOWDOWN->SLOWNESSDIG_SPEED->HASTEDIG_SLOWDOWN->MINING_FATIGUEDAMAGE_BOOST->STRENGTHHEAL->INSTANT_HEALTHHARM->INSTANT_DAMAGEJUMP->JUMP_BOOSTCONFUSION->NAUSEADAMAGE_RESISTANCE->RESISTANCE
非常技术性的变更
这是一个技术变更列表,根据您的具体设置可能导致高度特定的错误。
-
minecraft:patch_sugar_cane功能和minecraft:patch_pumpkin功能的顺序已交换(先南瓜,后甘蔗),这意味着生成这两个功能的模组生物群系需要将其 JSON 更新为新顺序。 -
几个原版橡树和树选择器功能现在末尾附加了
_leaf_litter。- 例如:
trees_birch_and_oak->trees_birch_and_oak_leaf_litter
- 例如:
新增列表
net.minecraftChatFormatting#COLOR_CODECCrashReportCategory#populateBlockLocationDetails- 将方块位置详细信息添加到崩溃报告。
net.minecraft.advancements.critereon.MinMaxBounds#createStreamCodec- 为MinMaxBounds实现构造一个流编解码器。net.minecraft.client.Options#startedCleanly- 设置游戏上次启动时是否干净启动。net.minecraft.client.data.modelsBlockModelGenerators#createSegmentedBlock- 生成一个具有水平旋转的多部分方块状态定义,根据某个整数属性显示最多四个模型。ItemModelGenerators#prefixForSlotTrim- 为某个槽位中的纹饰生成一个原版ResourceLocation。
net.minecraft.client.MouseHandlerfillMousePositionDetails- 将有关当前鼠标位置和屏幕大小的详细信息添加到崩溃报告。getScaledXPos- 获取由 GUI 缩放选项缩放的当前 x 位置。getScaledYPos- 获取由 GUI 缩放选项缩放的当前 y 位置。drawDebugMouseInfo- 将有关鼠标缩放位置的信息绘制到屏幕。
net.minecraft.client.gui.components.toasts.Toast#getSoundEvent- 返回显示吐司时要播放的声音。net.minecraft.client.gui.screens.options.VideoSettingsScreen#updateFullscreenButton- 将全屏选项设置为指定的布尔值。net.minecraft.client.model.geom.buildersMeshDefinition#apply- 在返回新实例之前将给定的变换器应用于网格。MeshTransformer#IDENTITY- 执行恒等变换。
net.minecraft.client.multiplayer.ClientPacketListener#decoratedHashOpsGenenerator- 返回用于创建数据组件及其值的哈希值的生成器。net.minecraft.client.particleFallingLeavesParticle$TintedLeavesProvider- 一个FallingLeavesParticle的提供者,使用粒子生成位置上方的方块指定的颜色。FireflyParticle- 一个在给定的非空气方块位置周围生成萤火虫的粒子。
net.minecraft.client.rendererBiomeColors#getAverageDryFoliageColor- 返回干燥生物群系的平均树叶颜色。LevelRenderer$BrightnessGetter- 一个在给定方块位置获取打包亮度的接口。WorldBorderRenderer#invalidate- 使世界边界的当前渲染无效,以便重新渲染。
net.minecraft.client.renderer.entityEntityRenderDispatcher#getRenderer- 从渲染状态上存储的数据中获取要使用的渲染器。EntityRenderer#extractAdditionalHitboxes- 当启用“显示碰撞箱”调试状态时,获取要渲染的任何其他碰撞箱。
net.minecraft.client.renderer.entity.stateEntityRenderStateentityType- 实体的类型。hitboxesRenderState- 相对于实体位置的实体的碰撞箱信息。serverHitboxesRenderState- 从服务器同步的实体的碰撞箱信息。fillCrashReportCategory- 设置与渲染状态相关的任何崩溃的详细信息。
HitboxesRenderState- 相对于实体位置的实体碰撞箱的渲染状态。HitboxRenderState- 要渲染的单个碰撞箱的渲染状态及其颜色,例如实体的眼睛高度。ServerHitboxesRenderState- 包含来自相关服务器实体的最后同步信息的渲染状态。PigRenderState#variant- 猪的变体。
net.minecraft.client.renderer.item.SelectItemModel$ModelSelector- 一个函数式接口,根据开关情况和级别选择物品模型。net.minecraft.client.renderer.item.properties.conditional.ComponentMatches- 一个条件属性,检查给定的谓词是否匹配组件数据。net.minecraft.client.renderer.item.properties.selectComponentContents- 一个开关情况属性,作用于数据组件内的内容。SelectItemModelProperty#valueCodec- 返回属性类型的Codec。
net.minecraft.client.resources.DryFoliageColorReloadListener- 一个加载干燥树叶颜色图的重新加载监听器。net.minecraft.commands.arguments.ComponentArgument#getResolvedComponent- 构造一个包含其内容已解析信息的组件。net.minecraft.coreDirection#getUnitVec3f- 返回方向的浮点单位向量。HolderGetter$Provider#getOrThrow- 从资源键获取一个持有者引用。SectionPos#sectionToChunk- 将压缩的部分位置转换为压缩的区块位置。Vec3i#STREAM_CODEC
net.minecraft.networkHashedPatchMap- 一个记录,包含组件到其哈希类型/值的映射,以及一组已移除的组件。HashedStack- 一个ItemStack表示,对存储的组件进行哈希处理。ProtocolInfo$DetailsProvider- 为给定的协议提供详细信息。SkipPacketDecoderException- 当解码期间发生错误时抛出的异常,其数据被忽略。SkipPacketEncoderException- 当编码期间发生错误时抛出的异常,其数据被忽略。
net.minecraft.network.chatLastSeenMessagescomputeChecksum- 计算表示所有消息签名的合并校验和的字节。$Update#verifyChecksum- 验证更新校验和是否与最后看到的消息中的校验和匹配。
LastSeenMessagesValidator$ValidationException- 如果无法验证消息则抛出的异常。MessageSignaturedescribe- 返回消息签名的字符串化版本。checksum- 将签名中的字节哈希为单个整数。
PlayerChatMessage#describeSigned- 返回聊天消息的字符串化版本。
net.minecraft.network.codecByteBufCodecsLONG_ARRAYlengthPrefixed- 返回一个将缓冲区大小限制为给定大小的操作。
IdDispatchCodec$DontDecorateException- 一个接口,告诉异常处理程序重新抛出原始异常,而不是将其包装在EncoderException中。
net.minecraft.network.protocolCodecModifier- 一个使用给定对象修改某个编解码器的函数。ProtocolInfoBuilder#context*Protocol- 使用给定的上下文构建一个UnboundProtocol,用于修改要发送的编解码器。
net.minecraft.network.protocol.game.GameProtocolsHAS_INFINITE_MATERIALS- 一个修饰符,检查ServerboundSetCreativeModeSlotPacket中玩家是否具有必要的设置。如果没有,则丢弃数据包。$Context- 返回数据包用于修改传入编解码器的上下文。
net.minecraft.resources.DelegatingOps$DelegateListBuilder- 一个列表构建器,如果需要可以被子类化。$DelegateRecordBuilder- 一个记录构建器,如果需要可以被子类化。
net.minecraft.server.bossevents.CustomBossEvent$Packed- 一个记录,支持用于序列化的事件信息。net.minecraft.server.commands.InCommandFunction- 一个接受某些输入并返回结果的命令函数。net.minecraft.server.levelDistanceManager#forEachBlockTickingChucnks- 为每个启用了方块Tick的区块应用提供的消费者。ServerLevelareEntitiesActuallyLoadedAndTicking- 返回实体管理器是否实际上正在Tick并加载给定区块中的实体。tickThunder- 在给定等级内Tick雷声逻辑。anyPlayerCloseEnoughForSpawning- 如果玩家足够接近以在给定位置生成实体,则返回。
ServerPlayer$RespawnConfig- 一个包含玩家重生信息的记录。
net.minecraft.utilAbstractListBuilder- 一个 ops 列表构建器,将实现简化为三个方法:初始化、追加和构建最终列表。Brightnessblock- 从打包值中返回块光。sky- 从打包值中返回天空光。
HashOps- 一个为数据生成哈希码的动态 ops。ExtraCodecsUNTRUSTED_URI- 一个不受游戏信任的 URI 的编解码器。CHAT_STRING- 聊天消息中字符串的编解码器。legacyEnum- 一个将枚举映射到其在Enum#toString中的输出的编解码器。
FileSystemUtil- 一个用于与文件系统交互的工具。GsonHelper#encodesLongerThan- 返回提供的元素是否可以用指定数量的字符写入。Unit#STREAM_CODEC- 一个用于单位实例的流编解码器。UtilmapValues- 使用给定的函数更新映射的值。mapValuesLazy- 使用给定的函数更新映射的值,但每个值在首次访问时解析。growByHalf- 返回一个整数乘以 1.5,向下取整,将值钳制到某个最小值和最大整数大小。
net.minecraft.util.random.Weighted#map、WeightedList#map- 将存储的对象转换为新类型。net.minecraft.util.thread.ParallelMapTransform- 一个辅助工具,用于并行处理和批处理任务。net.minecraft.world.effect.MobEffectInstance#withScaledDuration- 构造一个新的实例,其持续时间按某个浮点值缩放。net.minecraft.world.entityAreaEffectCloud#setPotionDurationScale- 设置药水应应用的持续时间比例。DropChances- 一个槽位到概率的映射,表示实体掉落该装备的可能性。EntityisInterpolating- 返回实体是否在两个步骤之间插值。sendBubbleColumnParticles- 从服务器生成气泡柱粒子。canSimulateMovement- 实体的移动是否可以模拟,通常来自玩家。propagateFallToPassengers- 将载具的坠落伤害传播给其乘客。lavaIgnite- 如果实体不免疫,则点燃实体 15 秒。clearFreeze- 将实体被冻结的刻数设置为 0。removeLatestMovementRecordingBatch- 从本Tick执行的所有移动中删除最后一个元素。
InterpolationHandler- 一个旨在根据需要轻松处理给定实体的位置和旋转插值的类。LivingEntitygetLuck- 返回实体在随机事件中的运气。getLastHurtByPlayer、setLastHurtByPlayer- 处理最后伤害此实体的玩家。getEffectBlendFactor- 获取已应用状态效果的混合因子。applyInput- 应用实体的输入作为其 AI,通常用于本地玩家。INPUT_FRICTION- 应用于实体移动的标量。
net.minecraft.world.entity.animal.camel.Camel#checkCamelSpawnRules- 检查骆驼是否可以在特定位置生成。net.minecraft.world.entity.animal.sheep.SheepColorSpawnRules- 一个包含绵羊在给定气候下生成时羊毛的颜色生成配置的类。net.minecraft.world.entity.npc.Villager#createDefaultVillagerData- 返回在未设置数据时要使用的村民的默认类型和职业。net.minecraft.world.entity.player.PlayerpreventsBlockDrops- 玩家是否不能掉落任何被破坏的方块。gameMode- 返回玩家的当前游戏模式。debugInfo- 将关于玩家的常见信息作为单个字符串返回。
net.minecraft.world.inventoryContainerSynchronizer#createSlot- 创建一个表示对侧槽位的RemoteSlot。RemoteSlot- 一个表示对侧数据的槽位,当数据不一致时进行同步。
net.minecraft.world.itemEitherHolder#key- 返回持有的注册表对象的资源键。Item#STREAM_CODECItemStackOPTIONAL_UNTRUSTED_STREAM_CODECMAP_CODECcanDestroyBlock- 返回此物品是否可以破坏提供的方块状态。
net.minecraft.world.item.alchemy.PotionContents#getPotionDescription- 返回带有某些放大器的状态效果的描述。net.minecraft.world.item.craftingRecipe#KEY_CODECTransmuteResult- 一个配方结果对象,表示一个物品、数量和应用到的组件。
net.minecraft.world.item.equipment.trim.ArmorTrim#layerAssetId- 返回纹饰资源的位置。net.minecraft.world.levelBlockGetter$BlockStepVisitor- 一个消费者,接受当前位置以及期望行进路径内的碰撞次数。ColorMapColorUtil- 一个辅助工具,根据生物群系的温度、降水、颜色映射和默认颜色从地图中获取颜色。DryFoliageColor- 用于具有干燥树叶的生物群系的颜色解析器。GameRulesgetType- 从其键获取游戏规则类型。keyCodec- 为游戏规则类型的键创建编解码器。
LevelisMoonVisible- 返回月亮当前是否在天空中可见。getPushableEntities- 获取指定目标之外的在提供的边界框内的所有实体。getClientLeafTintColor- 返回指定位置的树叶染色颜色。playPlayerSound- 在客户端向当前玩家播放声音。
LevelReader#getHeight- 返回地图在给定位置的高度。NaturalSpawner#INSCRIBED_SQUARE_SPAWN_DISTANCE_CHUNK- 提供玩家足够接近以进行生成的最小距离。
net.minecraft.world.level.biomeBiomegetDryFoliageColor、getDryFoliageColorFromTexture- 获取生物群系的干燥树叶颜色,要么从效果中获取,要么从气候设置中获取。
BiomeSpecialEffects#getDryFoliageColorOverride、$Builder#dryFoliageColorOverride- 当不从颜色映射纹理中提取时,返回默认的干燥树叶颜色。
net.minecraft.world.level.blockBaseFireBlock#fireIgnite- 点燃一个实体。BlockUPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS- 一个标志,在更新方块实体时跳过所有潜在的副作用。UPDATE_SKIP_ALL_SIDEEFFECTS- 一个标志,通过跳过某些方块实体逻辑、抑制掉落和更新已知形状来跳过所有副作用。UPDATE_SKIP_ON_PLACE- 一个标志,在设置时跳过调用BlockState#onPlace。
BonemealableBlock#hasSpreadableNeighbourPos、findSpreadableNeighbourPos- 处理在施骨粉时植被可以传播到的其他位置。CactusFlowerBlock- 生长在仙人掌上的花。FireflyBushBlock- 一个在其周围生成萤火虫粒子的灌木。SandBlock- 一个可以播放环境声音的彩色沙子方块。SegmentableBlock- 一个通常可以分解成具有独特大小和位置的部分的方块。ShortDryGrassBlock- 一个已经干枯的单个草方块。TallDryGrassBlock- 一个已经干枯的双高草方块。TerracottaBlock- 一个可以播放环境声音的陶瓦方块。TintParticleLeavesBlock- 一个其粒子被染色的树叶方块。UntintedParticleLeavesBlock- 一个其粒子未被染色的树叶方块。VegetationBlock- 一个表示某种植被的方块,可以传播光线,并需要某种耕地或泥土才能生存。
net.minecraft.world.level.block.entity.StructureBlockEntity#isStrict、setStrict- 在生成结构时设置严格模式。net.minecraft.world.level.block.sounds.AmbientDesertBlockSoundsPlayer- 一个辅助工具,用于为给定的方块播放声音,通常在animateTick期间。net.minecraft.world.level.block.state.BlockBehaviour#getEntityInsideCollisionShape- 获取实体在其内部时方块的碰撞形状。net.minecraft.world.level.border.WorldBorderclosestBorder- 根据玩家的水平方向返回离玩家最近的边界列表。$DistancePerDirection- 一个记录,包含给定方向上世界边界到实体的距离。
net.minecraft.world.level.chunk.status.ChunkStatus#CODECnet.minecraft.world.level.entity.PersistentEntitySectionManager#isTicking- 返回指定的区块当前是否正在Tick。net.minecraft.world.level.levelgen.Heightmap$Types#STREAM_CODECnet.minecraft.world.level.levelgen.featureAbstractHugeMushroomFeature#placeMushroomBlock- 在指定位置放置一个蘑菇方块,如果可以则替换方块。FallenTreeFeature- 一个生成带有给定长度树桩的倒伏树木的功能。TreeFeature#getLowestTrunkOrRootOfTree- 返回树装饰器的最低树干位置。
net.minecraft.world.level.levelgen.feature.configurations.FallenTreeConfiguration- 用于带有树桩的倒伏树的配置。net.minecraft.world.level.levelgen.feature.treedecoratorsAttachedToLogsDecorator- 一个装饰器,以一定的概率将随机方块附加到原木的给定方向。PlaceOnGroundDecorator- 一个装饰器,将树放置在有效的方块位置上。
net.minecraft.world.level.levelgen.structure.poolsListPoolElement#getElements- 返回结构池的元素。SinglePoolElement#getTemplateLocation- 返回元素使用的模板的位置。StructureTemplatePool#getTemplates- 返回一个带有权重的元素列表。
net.minecraft.world.level.levelgen.structure.structures.JigsawStructuregetStartPool- 返回要生成的拼图的起始池。getPoolAliases- 返回拼图使用的所有池。
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate#getDefaultJointType- 如果未指定或加载期间发生错误,返回两个拼图块之间的默认连接类型。net.minecraft.world.level.material.Fluid#getAABB、FluidState#getAABB- 返回流体的边界框。net.minecraft.world.scoresObjective#pack、$Packed- 处理目标数据的可序列化形式。PlayerTeam#pack、$Packed- 处理玩家队伍数据的可序列化形式。ScoreboardloadPlayerTeam、loadObjective- 从打包对象加载数据。$PackedScore- 处理记分板数据的可序列化形式。
net.minecraft.world.level.storage.loot.LootTable#KEY_CODECnet.minecraft.world.physAABB$Builder- 一个用于通过提供内部向量来构造边界框的构建器。Vec2#CODEC
net.minecraft.world.phys.shapes.CollisionContextplacementContext- 当从其物品放置方块时构造上下文。isPlacement- 返回上下文是否用于放置方块。
net.minecraft.world.ticks.TickPriority#CODEC
变更列表
net.minecraft.client.Screenshot现在是一个实用程序而不是实例类,意味着所有实例方法都已移除takeScreenshot(RenderTarget)->takeScreenshot(RenderTarget, Consumer<NativeImage>),不返回任何内容
net.minecraft.client.multiplayerClientChunkCache#replaceWithPacketData现在接受一个Map<Heightmap$Types, long[]>而不是CompoundTagMultiPlayerGameMode#hasInfiniteItems->net.minecraft.world.entity.LivingEntity#hasInfiniteMaterialsClientPacketListener#markMessageAsProcessed现在接受一个MessageSignature而不是PlayerChatMessage
net.minecraft.client.multiplayer.chat.ChatListener#handleChatMessageError现在接受一个可为 null 的MessageSignaturenet.minecraft.client.playerClientInput#leftImpulse、forwardImpulse->moveVector,现在是 protectedLocalPlayer#spinningEffectIntensity、oSpinningEffectIntensity->portalEffectIntensity、oPortalEffectIntensity
net.minecraft.client.renderer.LevelRenderer#getLightColor(BlockAndTintGetter, BlockState, BlockPos)->getLightColor(LevelRenderer$BrightnessGetter, BlockAndTintGetter, BlockState, BlockPos)net.minecraft.client.renderer.blockentity.BlockEntityRenderer#render现在接受一个Vec3表示相机的位置net.minecraft.client.renderer.chunk.SectionRenderDispatcher$RenderSectiongetOrigin->getRenderOriginreset现在是公开的releaseBuffers已移除
$CompileTask#getOrigin->getRenderOrigin
net.minecraft.client.renderer.entityDonkeyRenderer现在接受一个DonekyRenderer$Type,包含纹理、模型层和装备信息ItemEntityRenderer#renderMultipleFromCount现在有一个接受模型边界框的重载UndeadHorseRenderer现在接受一个UndeadHorseRenderer$Type,包含纹理、模型层和装备信息
net.minecraft.client.renderer.entity.layersEquipmentLayerRenderer$TrimSpriteKey#textureId->spriteIdVillagerProfessionLayer#getHatData现在接受一个资源键到元数据部分的映射,并将注册表和值交换为一个持有者实例
net.minecraft.client.renderer.itemConditionalItemModel现在接受一个ItemModelPropertyTest而不是ConditionalItemModelPropertySelectItemModel现在接受一个$ModelSelector而不是一个对象映射
net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperty现在实现ItemModelPropertyTestItemModelPropertyTest持有之前在ConditionalItemModelProperty中的get方法
net.minecraft.commands.argumentsComponentArgumentERROR_INVALID_JSON->ERROR_INVALID_COMPONENTgetComponent->getRawComponent
ResourceKeyArgument#getRegistryKey现在是公开的StyleArgument#ERROR_INVALID_JSON->ERROR_INVALID_STYLE
net.minecraft.commands.arguments.itemComponentPredicateParser$Context#createComponentTest、createPredicateTest现在接受一个Dynamic而不是TagItemPredicateArgument$ComponentWrapper#decode现在接受一个Dynamic而不是RegistryOps、Tag对$PredicateWrapper#decode现在接受一个Dynamic而不是RegistryOps、Tag对
net.minecraft.coreBlockMathVANILLA_UV_TRANSFORM_LOCAL_TO_GLOBAL、VANILLA_UV_TRANSFORM_GLOBAL_TO_LOCAL现在是私有的getUVLockTransform->getFaceTransformation
Direction#rotate现在接受一个Matrix4fc而不是Matrix4fRotations现在是一个记录
net.minecraft.data.loot.BlockLootSubProvider#createPetalDrops->createSegmentedBlockDropsnet.minecraft.networkFriendlyByteBufwriteLongArray、readLongArray现在有静态委托,接受ByteBuf,并且*Fixed*版本用于固定大小的数组
ProtocolInfo$Unbound->$Details、net.minecraft.network.protocol.SimpleUnboundProtocol、net.minecraft.network.protocol.UnboundProtocol;不是一对一#bind->net.minecraft.network.protocol.SimpleUnboundProtocol#bind、UnboundProtocol#bind;不是一对一
SkipPacketException现在是一个接口,而不是EncoderException的子类
net.minecraft.network.chatComponentSerialization#flatCodec->flatRestrictedCodecLastSeenMessages$Update现在接受一个表示校验和值的字节LastSeenMessagesValidatorapplyOffset现在不返回任何内容,并且可以抛出$ValidationExceptionapplyUpdate现在返回原始消息,并且可以抛出$ValidationException
net.minecraft.network.codec.StreamCodec#composite现在有一个九个参数的重载net.minecraft.network.protocol.ProtocolInfoBuilder现在接受第三个泛型,表示如何修改提供的编解码器。addPacket现在有一个接受CodecModifier的重载build->buildUnbound,不是一对一protocol、serverboundProtocol、clientboundProtocol现在返回一个SimpleUnboundProtocol
net.minecraft.network.protocol.ConfigurationProtocols现在包含SimpleUnboundProtocol常量net.minecraft.network.protocol.gameClientboundContainerSetContentPacket现在是一个记录ClientboundMoveEntityPacket#getyRot、getxRot->getYRot、getXRotClientboundPlayerChatPacket现在接受一个聊天消息的全局索引ClientboundLevelChunkPacketdata#getHeightmaps现在返回一个Map<Heightmap.Types, long[]>ClientboundUpdateAdvancementsPacket现在接受一个布尔值,表示是否将进度显示为吐司GameProtocols常量现在是SimpleUnboundProtocol或UnboundProtocolServerboundContainerClickPacket现在是一个记录ServerboundMovePlayerPacket$Pos、$PosRot现在有一个接受Vec3作为位置的重载ServerboundSetStructureBlockPacket现在接受一个额外的布尔值,表示是否应在严格模式下生成结构
net.minecraft.network.protocol.handshake.HandshakeProtocols#SERVERBOUND_TEMPLATE现在是一个SimpleUnboundProtocolnet.minecraft.network.protocol.login.LoginProtocols#SERVERBOUND_TEMPLATE常量现在是SimpleUnboundProtocolnet.minecraft.network.protocol.status.StatusProtocols#SERVERBOUND_TEMPLATE常量现在是SimpleUnboundProtocolnet.minecraft.server.PlayerAdvancements#flushDirty现在接受一个布尔值,表示进度是否显示为吐司net.minecraft.server.bossevents.CustomBossEventsave->pack,不是一对一load现在接受 id 和打包变体以解包
net.minecraft.server.levelDistanceManagerhasPlayersNearby现在返回一个TriStateforEachBlockTickingChunks->forEachEntityTickingChunk,不是一对一
ServerEntity现在接受一个消费者,用于向所有玩家广播数据包,但忽略列表中的玩家除外ServerLevelgetForcedChunks->getForceLoadedChunksisPositionTickingWithEntitiesLoaded现在是公开的isNaturalSpawningAllowed->canSpawnEntitiesInChunk,BlockPos变体已移除
ServerPlayergetRespawnPosition、getRespawnAngle、getRespawnDimension、isRespawnForced->getRespawnConfig,不是一对一setRespawnPosition现在接受一个$RespawnConfig而不是单独的重生信息loadAndSpawnParentVehicle、loadAndSpawnEnderpearls现在接受一个CompoundTag,没有可选的包装
net.minecraft.server.network.ServerGamePacketListenerImpl现在实现GameProtocols$Contextnet.minecraft.sounds.SoundEvents有以下声音现在是Holder包装的:ITEM_BREAKSHIELD_BLOCK、SHIELD_BREAK、WOLF_ARMOR_BREAK
net.minecraft.utilBrightnessFULL_BRIGHT现在是 finalpack现在有一个静态重载,接受块光和天空光。
ExtraCodecs#MATRIX4f现在是一个Codec<Matrix4fc>Util#makeEnumMap返回Map超实例而不是具体的EnumMap
net.minecraft.util.parsing.packrat.commands.TagParseRule现在接受一个标签类型的泛型- 构造函数现在是公开的,接受一个
DynamicOps
- 构造函数现在是公开的,接受一个
net.minecraft.util.profilingActiveProfiler现在接受一个BooleanSupplier而不是一个布尔值ContinuousProfiler现在接受一个BooleanSupplier而不是一个布尔值
net.minecraft.util.worldupdate.WorldUpgrader现在接受当前的WorldDatanet.minecraft.worldBossEvent$BossBarColor、$BossBarOverlay现在实现StringRepresentableContainer现在实现Iterable<ItemStack>
net.minecraft.world.effectMobEffectgetBlendDurationTicks->getBlendInDurationTicks、getBlendOutDurationTicks、getBlendOutAdvanceTicks;不是一对一setBlendDuration现在有一个接受三个整数来设置淡入、淡出和淡出提前刻的重载
MobEffectInstance#tick->tickServer、tickClient;不是一对一
net.minecraft.world.entityEntitycancelLerp->InterpolationHandler#cancellerpTo->moveOrInterpolateTolerpTargetX、lerpTargetY、lerpTargetZ、lerpTargetXRot、lerpTargetYRot->getInterpolationonAboveBubbleCol->onAboveBubbleColumn现在接受一个BlockPos作为气泡柱粒子的生成位置- 逻辑委托给受保护的静态
handleOnAboveBubbleColumn
- 逻辑委托给受保护的静态
isControlledByOrIsLocalPlayer->isLocalInstanceAuthoritative,现在是 finalisControlledByLocalInstance->isLocalClientAuthoritative,现在是 protectedisControlledByClient->isClientAuthoritativefallDistance、causeFallDamage现在是 doubleabsMoveto->absSnapToabsRotateTo->asbSnapRotationTomoveTo->snapTosendBubbleColumnParticles现在是静态的,接受LevelonInsideBubbleColumn逻辑委托给受保护的静态handleOnInsideBubbleColumn
EntityTypePOTION->SPLASH_POTION、LINGERING_POTION,不是一对一$EntityFactory#create现在可以返回一个 null 实例
ExperienceOrb#value->DATA_VALUEItemBasedSteering不再接受用于判断是否有马鞍的访问器LivingEntitylastHurtByPlayerTime->lastHurtByPlayerMemoryTimelerpSteps、lerpX、lerpY、lerpZ、lerpYRot、lerpXRot->interpolation,不是一对一isAffectedByFluids现在是公开的removeEffectNoUpdate现在是 finaltickHeadTurn现在不返回任何内容canDisableShield->canDisableBlocking,现在通过WEAPON数据组件设置calculateFallDamage现在接受 double 而不是 float
MobhandDropChances、armorDropChances、bodyArmorDropChance->dropChances,不是一对一getEquipmentDropChance->getDropChances,不是一对一
net.minecraft.world.entity.ai.Brain#addActivityWithConditions现在有一个接受整数表示起始优先级的重载net.minecraft.world.entity.ai.behaviorLongJumpToRandomPos$PossibleJump现在是一个记录VillagerGoalPackages#get*Package现在接受一个持有者包装的职业
net.minecraft.world.entity.ai.gossip.GossipContainer#store、update->clear、putAll、copy;不是一对一net.minecraft.world.entity.animalPig现在是一个VariantHolderSheep->.sheep.SheepWaterAnimal#handleAirSupply现在接受一个ServerLevel
net.minecraft.world.entity.animal.axolotl.Axolotl#handleAirSupply现在接受一个ServerLevelnet.minecraft.world.entity.monster.ZombieVillager#setGossips现在接受一个GossipContainernet.minecraft.world.entity.monster.warden.WardenSpawnTracker现在有一个重载,将初始参数设置为零net.minecraft.world.entity.npcVillager现在接受一个键或一个VillagerType的持有者setGossips现在接受一个GossipContainer
VillagerData现在是一个记录set*->with*
VillagerProfession现在接受一个Component作为名称VillagerTradesTRADES现在接受一个资源键作为映射的键- 这对于所有其他特定类型的交易类似
$FailureItemListing现在是私有的
net.minecraft.world.entity.player.PlayerstopFallFlying->LivingEntity#stopFallFlyingisSpectator、isCreative在Player类中不再是抽象的
net.minecraft.world.entity.projectile.ThrownPotion->AbstractThrownPotion,在ThrownLingeringPotion和ThrownSplashPotion中实现net.minecraft.world.entity.raid.Raid(int, ServerLevel, BlockPos)->Raid(BlockPos, Difficulty)tick、addWaveMob现在接受ServerLevel
net.minecraft.world.entity.vehicleAbstractMinecart#setDisplayBlockState->setCustomDisplayBlockStateMinecartBehaviorcancelLerp->InterpolationHandler#cancellerpTargetX、lerpTargetY、lerpTargetZ、lerpTargetXRot、lerpTargetYRot->getInterpolation
MinecartTNT#primeFuse现在接受DamageSource原因
net.minecraft.world.inventoryAbstractContainerMenusetRemoteSlotNoCopy->setRemoteSlotUnsafe,不是一对一setRemoteCarried现在接受一个HashedStack
ClickType现在接受一个表示其表示的 idContainerSynchronizer#sendInitialData现在接受一个堆栈列表而不是NonNullList
net.minecraft.world.itemEitherHolder现在接受一个Either实例而不是仅仅一个可选的持有者和ResourceKeyItemcanAttackBlock->canDestroyBlockhurtEnemy不再返回任何内容onCraftedBy不再接受一个单独的Level实例,现在依赖于Player提供的实例
ItemStackvalidateStrict现在是公开的onCraftedBy不再接受一个单独的Level实例,现在依赖于Player提供的实例
MapItemcreate现在接受一个ServerLevel而不是LevellockMap现在是私有的
ThrowablePotionItem现在是抽象的,包含两个创建AbstractThrownPotion实体的方法WrittenBookItem#resolveBookComponents->WrittenBookContent#resolveForItem
net.minecraft.world.item.alchemy.PotionContents现在实现TooltipProviderforEachEffect、applyToLivingEntity现在接受一个 float 表示持续时间的标量
net.minecraft.world.item.component.WrittenBookContent现在实现TooltipProvidernet.minecraft.world.item.craftingSmithingRecipe#baseIngredient现在返回一个IngredientSmithingTransformRecipe现在接受一个TransmuteResult而不是一个ItemStack和一个Ingredient作为基础SmithingTrimRecipe现在接受Ingredient而不是Optional包装的条目,以及一个TrimPattern持有者TransmuteRecipe现在接受一个TransmuteResult而不是一个Item持有者
net.minecraft.world.item.crafting.display.SlotDisplay$SmithingTrimDemoSlotDisplay现在接受一个TrimPattern持有者net.minecraft.world.item.enchantment.EnchantmentInstance现在是一个记录net.minecraft.world.levelBlockGetter#boxTraverseBlocks->forEachBlockIntersectedBetween,不是一对一CustomSpawner#tick不再返回任何内容GameRules$Type现在接受一个值类LevelonBlockStateChange->updatePOIOnBlockStateChangeisDay->isBrightOutsideisNight->isDarkOutsidesetMapData->net.minecraft.server.level.ServerLevel#setMapDatagetFreeMapId->net.minecraft.server.level.ServerLevel#getFreeMapId
LevelAccessor#blockUpdated->updateNeighborsAt
net.minecraft.world.level.biome.MobSpawnSettings$SpawnerData现在是一个记录net.minecraft.world.level.blockAttachedStemBlock现在继承VegetationBlockAzaleaBlock现在继承VegetationBlockBlock#fallOn现在接受一个 double 作为坠落伤害,而不是 floatBushBlock现在继承VegetationBlock并实现BonemealableBlockColoredFallingBlock#dustColor现在是 protectedCropBlock现在继承VegetationBlockDeadBushBlock->DryVegetationBlockDoublePlantBlock现在继承VegetationBlockFallingBlock#getDustColor现在是抽象的FlowerBedBlock现在继承VegetationBlockFlowerBlock现在继承VegetationBlockFungusBlock现在继承VegetationBlockLeafLitterBlock现在继承VegetationBlockLeavesBlock现在是抽象的,接受粒子生成的概率- 粒子通过
spawnFallingLeavesParticle生成
- 粒子通过
MangroveLeavesBlock现在继承TintedParticleLeavesBlockMushroomBlock现在继承VegetationBlockNetherSproutsBlock现在继承VegetationBlockNetherWartBlock现在继承VegetationBlockParticleLeavesBlock->LeafLitterBlockPinkPetalsBlock->FlowerBedBlockRootsBlock现在继承VegetationBlockRotation现在有一个用于网络同步的索引SaplingBlock现在继承VegetationBlockSeagrassBlock现在继承VegetationBlockSeaPickleBlock现在继承VegetationBlockStemBlock现在继承VegetationBlockSweetBerryBushBlock现在继承VegetationBlockTallGrassBlock现在继承VegetationBlockTntBlock#prime现在返回是否生成了点燃的 TNT。WaterlilyBlock现在继承VegetationBlock
net.minecraft.world.level.block.entityBlockEntityparseCustomNameSafe现在接受一个可为 null 的Tag而不是字符串getPosFromTag现在接受ChunkPos$ComponentHolder#COMPONENTS_CODEC现在是一个MapCodec
BLockEntityType#create不再是可为 null 的
net.minecraft.world.level.block.entity.trialspawner.TrialSpawner#codec现在返回一个MapCodecnet.minecraft.world.level.block.state.StateHoldergetNullableValue现在是私有的hasProperty不再包含泛型
net.minecraft.world.level.chunkChunkAccess#setBlockState现在接受块标志而不是布尔值,并有一个重载来更新所有设置LevelChunk#replaceWithPacketData现在接受一个Map<Heightmap$Types, long[]>而不是CompoundTag
net.minecraft.world.level.chunk.storage.SerializableChunkData#getChunkTypeFromTag->getChunkStatusFromTag,不是一对一net.minecraft.world.level.gameevent.vibrations.VibrationSystem#DEFAULT_VIBRATION_FREQUENCY->NO_VIBRATION_FREQUENCYnet.minecraft.world.level.levelgen.feature.TreeFeature#isVine现在是公开的net.minecraft.world.level.levelgen.structure.pools.aliasDirect->DirectPoolAliasRandom->RandomPoolAliasRandomGroup->RandomGroupPoolAlias
net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate$JigsawBlockInfo现在接受StructureTemplatePool的ResourceKey而不是原始ResourceLocationnet.minecraft.world.level.saveddata.maps.MapFrame现在是一个记录save、load->CODEC,不是一对一
net.minecraft.world.level.storage.loot.functions.SetWrittenBookPagesFunction#PAGE_CODEC->WrittenBookContent#PAGES_CODECnet.minecraft.world.scoresScore#write->CODEC,不是一对一ScoreboardsavePlayerScores->packPlayerScores,不是一对一loadPlayerScores->loadPlayerScore,不是一对一
Team$CollisionRule、$Visibility现在是StringRepresentable
net.minecraft.world.phys.shapes.EntityCollisionContext现在接受一个布尔值,表示是否用于放置方块net.minecraft.world.ticks.SavedTickloadTick、saveTick、save->codec,不是一对一loadTickList->filterTickListForChunk,不是一对一
移除列表
com.mojang.blaze3d.vertex.BufferUploadernet.minecraft.core.Rotations#getWrapped*net.minecraft.network.chat.ComponentSerialization#FLAT_CODECnet.minecraft.network.protocol.gameClientboundAddExperimentOrbPacketClientGamePacketListener#handleAddExperienceOrb
net.minecraft.resources.ResourceLocation$Serializernet.minecraft.server.network.ServerGamePacketListenerImpl#addPendingMessagenet.minecraft.worldBossEvent$BossBarColor#byName、$BossBarOverlay#byNameClearable#tryClear
net.minecraft.world.effect.MobEffectInstance#save、loadnet.minecraft.world.entityEntityisInBubbleColumnisInWaterRainOrBubble、isInWaterOrBubblenewDoubleList、newFloatListrecordMovementThroughBlocks
EntityEvent#ATTACK_BLOCKED、SHIELD_DISABLEDItemBasedSteeringaddAdditionalSaveData、readAdditionalSaveDatasetSaddle、hasSadddle
LivingEntitytimeOffs、rotOffsrotAoRun、runanimStep、animStep0appliedScalecanBeNameTagged
MobDEFAULT_EQUIPMENT_DROP_CHANCEPRESERVE_ITEM_DROP_CHANCE_THRESHOLD、PRESERVE_ITEM_DROP_CHANCE
NeutralMob#setLastHurtByPlayerPositionMoveRotation#ofEntityUsingLerpTarget
net.minecraft.world.entity.ai.attributes.AttributeModifier#save、loadnet.minecraft.world.entity.animalDolphin#setTreasurePos、getTreasurePosFox$Variant#byNameMushroomCow$Variant#byNamePanda$Gene#byNameSalmon$Variant#byNameTurtlegetHomePossetTravelPos、getTravelPosisGoingHome、setGoingHomeisTravelling、setTravelling
net.minecraft.world.entity.animal.armadillo.Armadillo$ArmadilloState#fromNamenet.minecraft.world.entity.npc.VillagerTrades#EXPERIMENTAL_WANDERING_TRADER_TRADESnet.minecraft.world.entity.projectile.AbstractArrow#getBaseDamagenet.minecraft.world.entity.raid.RaidgetLevel、getIdsave
net.minecraft.world.entity.vehicle.AbstractMinecart#hasCustomDisplay、setCustomDisplaynet.minecraft.world.item.ItemStack#parseOptional、saveOptionalnet.minecraft.world.item.equipment.trim.TrimPattern#templateItemnet.minecraft.world.level.Level#updateNeighborsAt(BlockPos, Block)net.minecraft.world.level.block.entityCampfireBlockEntity#dowsePotDecorations#save、load
net.minecraft.world.level.levelgen.BelowZeroRetrogen#readnet.minecraft.world.level.levelgen.structure.structures.RuinedPortalPiece$VerticalPlacement#byNamenet.minecraft.world.level.saveddata.maps.MapBanner#LIST_CODECnet.minecraft.world.scores.Team$CollisionRule#byName$Visibility#getAllNames、byName
net.minecraft.world.ticks.LevelChunkTicks#save、load