# Minecraft 1.21.10 -> 1.21.11 模组迁移入门文档 本文档是一个高层次、非详尽的概述,介绍如何将您的模组从 1.21.10 迁移到 1.21.11。本文不涉及任何特定的模组加载器,只关注原版类的变更。所有提供的名称均使用官方的 Mojang 映射。 本入门文档采用 [知识共享署名 4.0 国际许可协议](http://creativecommons.org/licenses/by/4.0/) 授权,因此您可以自由地将其用作参考,并请留下链接以便其他读者查阅。 如果存在任何不正确或缺失的信息,请在本仓库提交 issue,或在 Neoforged Discord 服务器中 @ChampionAsh5357。 感谢: - @xfacthd 对使用注解的一些合理推测 - @dinnerbone 指出在单机世界中,gizmo 也可以在服务器上提交 - @thatgravyboat 指出 `Mth#clampedLerp` 参数顺序的变化 ## 资源包变更 原版中有许多面向用户的变更为未在下面讨论,但这些变更可能与模组制作者相关。您可以在 [Misode 的版本更新日志](https://misode.github.io/versions/?id=1.22&tab=changelog) 中找到它们的列表。 ## 重命名混乱 许多核心类、方法和参数被重新组织和重命名,同时保留了它们各自的功能。以下是最重要变更的列表。 ### `ResourceLocation` 到 `Identifier` 所有对 `ResourceLocation` 的引用,无论是在方法名称、参数还是其他类中,都已替换为 `Identifier`。 ### `util` 包 大多数工具类已移至 `net.minecraft.util`。这些需要重新导入。 ### `critereon` 到 `criterion` `net.minecraft.advancements.critereon` 已重命名为 `net.minecraft.advancements.criterion`。这些需要重新导入。 ### 实体和对象子包 `net.minecraft.client.model` 和 `net.minecraft.world.entity` 都已根据支持对象的类型重新组织为额外的子包。这些需要重新导入。 - `net.minecraft` - `BlockUtil` -> `.util.BlockUtil` - `FileUtil` -> `.util.FileUtil` - `ResourceLocationException` -> `IdentifierException` - `Util` -> `.util.Util` - `net.minecraft.advancements.critereon` -> `.advancements.criterion` - `net.minecraft.client.gui.screens.inventory.JigsawBlockEditScreen#isValidResourceLocation` -> `isValidIdentifier` - `net.minecraft.client.model` - `AbstractBoatModel` -> `.object.boat.AbstractBoatModel` - `AbstractEquineModel` -> `.animal.equine.AbstractEquineModel` - `AbstractPiglinModel` -> `.monster.piglin.AbstractPiglinModel` - `AbstractZombieModel` -> `.monster.zombie.AbstractZombieModel` - `AllayModel` -> `.animal.allay.AllayModel` - `ArmadilloModel` -> `.animal.armadillo.ArmadilloModel` - `ArmorStandArmorModel` -> `.object.armorstand.ArmorStandArmorModel` - `ArmorStandModel` -> `.object.armorstand.ArmorStandModel` - `ArrowModel` -> `.object.projectile.ArrowModel` - `AxolotlModel` -> `.animal.axolotl.AxolotlModel` - `BannerFlagModel` -> `.object.banner.BannerFlagModel` - `BannerModel` -> `.object.banner.BannerModel` - `BatModel` -> `.ambient.BatModel` - `BeeModel` -> `.animal.bee.BeeModel` - `BeeStingerModel` -> `.animal.bee.BeeStingerModel` - `BellModel` -> `.object.bell.BellModel` - `BlazeModel` -> `.monster.blaze.BlazeModel` - `BoatModel` -> `.object.boat.BoatModel` - `BoggedModel` -> `.monster.skeleton.BoggedModel` - `BookModel` -> `.object.book.BookModel` - `BreezeModel` -> `.monster.breeze.BreezeModel` - `CamelModel` -> `.animal.camel.CamelModel` - `CamelSaddleModel` -> `.animal.camel.CamelSaddleModel` - `CatModel` -> `.animal.feline.CatModel` - `ChestModel` -> `.object.chest.ChestModel` - `ChickenModel` -> `.animal.chicken.ChickenModel` - `CodModel` -> `.animal.fish.CodModel` - `ColdChickenModel` -> `.animal.chicken.ColdChickenModel` - `ColdCowModel` -> `.animal.cow.ColdCowModel` - `ColdPigModel` -> `.animal.pig.ColdPigModel` - `CopperGolemModel` -> `.animal.golem.CopperGolemModel` - `CopperGolemStatueModel` -> `.object.statue.CopperGolemStatueModel` - `CowModel` -> `.animal.cow.CowModel` - `CreakingModel` -> `.monster.creaking.CreakingModel` - `CreeperModel` -> `.monster.creeper.CreeperModel` - `DolphinModel` -> `.animal.dolphin.DolphinModel` - `DonkeyModel` -> `.animal.equine.DonkeyModel` - `DrownedModel` -> `.monster.zombie.DrownedModel` - `ElytraModel` -> `.object.equipment.ElytraModel` - `EndCrystalModel` -> `.object.crystal.EndCrystalModel` - `EndermanModel` -> `.monster.enderman.EndermanModel` - `EndermiteModel` -> `.monster.endermite.EndermiteModel` - `EquineSaddleModel` -> `.animal.equine.EquineSaddleModel` - `EvokerFangsModel` -> `.effects.EvokerFangsModel` - `FelineModel` -> `.animal.feline.FelineModel` - `FoxModel` -> `.animal.fox.FoxModel` - `FrogModel` -> `.animal.frog.FrogModel` - `GhastModel` -> `.monster.ghast.GhastModel` - `GiantZombieModel` -> `.monster.zombie.GiantZombieModel` - `GoatModel` -> `.animal.goat.GoatModel` - `GuardianModel` -> `.monster.guardian.GuardianModel` - `GuardianParticleModel` -> `.monster.guardian.GuardianParticleModel` - `HappyGhastHarnessModel` -> `.animal.ghast.HappyGhastHarnessModel` - `HappyGhastModel` -> `.animal.ghast.HappyGhastModel` - `HoglinModel` -> `.monster.hoglin.HoglinModel` - `HorseModel` -> `.animal.equine.HorseModel` - `IllagerModel` -> `.monster.illager.IllagerModel` - `IronGolemModel` -> `.animal.golem.IronGolemModel` - `LavaSlimeModel` -> `.monster.slime.MagmaCubeModel` - `LeashKnotModel` -> `.object.leash.LeashKnotModel` - `LlamaModel` -> `.animal.llama.LlamaModel` - `LlamaSpitModel` -> `.animal.llama.LlamaSpitModel` - `MinecartModel` -> `.object.cart.MinecartModel` - `OcelotModel` -> `.animal.feline.OcelotModel` - `PandaModel` -> `.animal.panda.PandaModel` - `ParrotModel` -> `.animal.parrot.ParrotModel` - `PhantomModel` -> `.monster.phantom.PhantomModel` - `PiglinHeadModel` -> `.object.skull.PiglinHeadModel` - `PiglinModel` -> `.monster.piglin.PiglinModel` - `PigModel` -> `.animal.pig.PigModel` - `PlayerCapeModel` -> `.player.PlayerCapeModel` - `PlayerEarsModel` -> `.player.PlayerEarsModel` - `PlayerModel` -> `.player.PlayerModel` - `PolarBearModel` -> `.animal.polarbear.PolarBearModel` - `PufferfishBigModel` -> `.animal.fish.PufferfishBigModel` - `PufferfishMidModel` -> `.animal.fish.PufferfishMidModel` - `PufferfishSmallModel` -> `.animal.fish.PufferfishSmallModel` - `RabbitModel` -> `.animal.rabbit.RabbitModel` - `RaftModel` -> `.object.boat.RaftModel` - `RavagerModel` -> `.monster.ravager.RavagerModel` - `SalmonModel` -> `.animal.fish.SalmonModel` - `SheepFurModel` -> `.animal.sheep.SheepFurModel` - `SheepModel` -> `.animal.sheep.SheepModel` - `ShieldModel` -> `.object.equipment.ShieldModel` - `ShulkerBulletModel` -> `.object.projectile.ShulkerBulletModel` - `ShulkerModel` -> `.monster.shulker.ShulkerModel` - `SilverfishModel` -> `.monster.silverfish.SilverfishModel` - `SkeletonModel` -> `.monster.skeleton.SkeletonModel` - `SkullModel` -> `.object.skull.SkullModel` - `SkullModelBase` -> `.object.skull.SkullModelBase` - `SlimeModel` -> `.monster.slime.SlimeModel` - `SnifferModel` -> `.animal.sniffer.SnifferModel` - `SnowGolemModel` -> `.animal.golem.SnowGolemModel` - `SpiderModel` -> `.monster.spider.SpiderModel` - `SpinAttackEffectModel` -> `.effects.SpinAttackEffectModel` - `SquidModel` -> `.animal.squid.SquidModel` - `StriderModel` -> `.monster.strider.StriderModel` - `TadpoleModel` -> `.animal.frog.TadpoleModel` - `TridentModel` -> `.object.projectile.TridentModel` - `TropicalFishModelA` -> `.animal.fish.TropicalFishSmallModel` - `TropicalFishModelB` -> `.animal.fish.TropicalFishLargeModel` - `TurtleModel` -> `.animal.turtle.TurtleModel` - `VexModel` -> `.monster.vex.VexModel` - `VillagerModel` -> `.npc.VillagerModel` - `WardenModel` -> `.monster.warden.WardenModel` - `WarmCowModel` -> `.animal.cow.WarmCowModel` - `WindChargeModel` -> `.object.projectile.WindChargeModel` - `WitchModel` -> `.monster.witch.WitchModel` - `WitherBossModel` -> `.monster.wither.WitherBossModel` - `WolfModel` -> `.animal.wolf.WolfModel` - `ZombieModel` -> `.monster.zombie.ZombieModel` - `ZombieVillagerModel` -> `.monster.zombie.ZombieVillagerModel` - `ZombifiedPiglinModel` -> `.monster.piglin.ZombifiedPiglinModel` - `net.minecraft.client.model.dragon` - `DragonHeadModel` -> `.model.object.skull.DragonHeadModel` - `EnderDragonModel` -> `.model.monster.dragon.EnderDragonModel` - `net.minecraft.client.resources.sounds` - `AbstractSoundInstance#location` -> `identifier` - `SoundInstance#getLocation` -> `getIdentifier` - `net.minecraft.client.searchtree` - `IdSearchTree` - `resourceLocationSearchTree` -> `identifierSearchTree` - `searchResourceLocation` -> `searchIdentifier` - `ResourceLocationSearchTree` -> `IdentifierSearchTree` - `net.minecraft.commands.arguments.ResourceLocationArgument` -> `IdentifierArgument` - `net.minecraft.network.FriendlyByteBuf#readResourceLocation`, `writeResourceLocation` -> `readIdentifier`, `writeIdentifier` - `net.minecraft.resources` - `ResourceKey#location` -> `identifier` - `ResourceLocation` -> `Identifier` - `net.minecraft.util.ResourceLocationPattern` -> `IdentifierPattern` - `net.minecraft.util.parsing.packrat.commands.ResourceLocationParseRule` -> `IdentifierParseRule` - `net.minecraft.world.entity.GlowSquid` -> `.animal.squid.GlowSquid` - `net.minecraft.world.entity.animal` - `AbstractCow` -> `.cow.AbstractCow` - `AbstractFish` -> `.fish.AbstractFish` - `AbstractGolem` -> `.golem.AbstractGolem` - `AbstractSchoolingFish` -> `.fish.AbstractSchoolingFish` - `Bee` -> `.bee.Bee` - `Cat` -> `.feline.Cat` - `CatVariant` -> `.feline.CatVariant` - `CatVariants` -> `.feline.CatVariants` - `Chicken` -> `.chicken.Chicken` - `ChickenVariant` -> `.chicken.ChickenVariant` - `ChickenVariants` -> `.chicken.ChickenVariants` - `Cod` -> `.fish.Cod` - `Cow` -> `.cow.Cow` - `CowVariant` -> `.cow.CowVariant` - `CowVariants` -> `.cow.CowVariants` - `Dolphin` -> `.dolphin.Dolphin` - `Fox` -> `.fox.Fox` - `HappyGhast` -> `.happyghast.HappyGhast` - `HappyGhastAi` -> `.happyghast.HappyGhastAi` - `IronGolem` -> `.golem.IronGolem` - `MushroomCow` -> `.cow.MushroomCow` - `Ocelot` -> `.feline.Ocelot` - `Panda` -> `.panda.Panda` - `Parrot` -> `.parrot.Parrot` - `Pig` -> `.pig.Pig` - `PigVariant` -> `.pig.PigVariant` - `PigVariants` -> `.pig.PigVariants` - `PolarBear` -> `.polarbear.PolarBear` - `Pufferfish` -> `.fish.Pufferfish` - `Rabbit` -> `.rabbit.Rabbit` - `Salmon` -> `.fish.Salmon` - `ShoulderRidingEntity` -> `.parrot.ShoulderRidingEntity` - `SnowGolem` -> `.golem.SnowGolem` - `Squid` -> `.squid.Squid` - `TropicalFish` -> `.fish.TropicalFish` - `Turtle` -> `.turtle.Turtle` - `WaterAnimal` -> `.fish.WaterAnimal` - `net.minecraft.world.entity.animal.coppergolem.*` -> `.animal.golem.*` - `net.minecraft.world.entity.animal.horse.*` -> `.animal.equine.*` - `net.minecraft.world.entity.boss.EnderDragonPart` -> `.enderdragon.EnderDragonPart` - `net.minecraft.world.entity.decoration` - `Painting` -> `.painting.Painting` - `PaintingVariant` -> `.painting.PaintingVariant` - `PaintingVariants` -> `.painting.PaintingVariants` - `net.minecraft.world.entity.monster` - `AbstractIllager` -> `.illager.AbstractIllager` - `AbstractSkeleton` -> `.skeleton.AbstractSkeleton` - `Bogged` -> `.skeleton.Bogged` - `CaveSpider` -> `.spider.CaveSpider` - `Drowned` -> `.zombie.Drowned` - `Evoker` -> `.illager.Evoker` - `Husk` -> `.zombie.Husk` - `Illusioner` -> `.illager.Illusioner` - `Parched` -> `.skeleton.Parached` - `Pillager` -> `.illager.Pillager` - `Skeleton` -> `.skeleton.Skeleton` - `SpellcasterIllager` -> `.illager.SpellcasterIllager` - `Spider` -> `.spider.Spider` - `Stray` -> `.skeleton.Stray` - `Vindicator` -> `.illager.Vindicator` - `WitherSkeleton` -> `.skeleton.WitherSkeleton` - `Zombie` -> `.zombie.Zombie` - `ZombieVillager` -> `.zombie.ZombieVillager` - `ZombifiedPiglin` -> `.zombie.ZombifiedPiglin` - `net.minecraft.world.entity.npc` - `AbstractVillager` -> `.villager.AbstractVillager` - `Villager` -> `.villager.Villager` - `VillagerData` -> `.villager.VillagerData` - `VillagerDataHolder` -> `.villager.VillagerDataHolder` - `VillagerProfession` -> `.villager.VillagerProfession` - `VillagerTrades` -> `.villager.VillagerTrades` - `VillagerType` -> `.villager.VillagerType` - `WanderingTrader` -> `.wanderingtrader.WanderingTrader` - `WanderingTraderSpawner` -> `.wanderingtrader.WanderingTraderSpawner` - `net.minecraft.world.entity.projectile` - `AbstractArrow` -> `.arrow.AbstractArrow` - `AbstractHurtingProjectile` -> `.hurtingprojectile.AbstractHurtingProjectile` - `AbstractThrownPotion` -> `.throwableitemprojectile.AbstractThrownPotion` - `Arrow` -> `.arrow.Arrow` - `DragonFireball` -> `.hurtingprojectile.DragonFireball` - `Fireball` -> `.hurtingprojectile.Fireball` - `LargeFireball` -> `.hurtingprojectile.LargeFireball` - `SmallFireball` -> `.hurtingprojectile.SmallFireball` - `Snowball` -> `.throwableitemprojectile.Snowball` - `SpectralArrow` -> `.arrow.SpectralArrow` - `ThrowableItemProjectile` -> `.throwableitemprojectile.ThrowableItemProjectile` - `ThrownEgg` -> `.throwableitemprojectile.ThrownEgg` - `ThrownEnderpearl` -> `.throwableitemprojectile.ThrownEnderpearl` - `ThrownExperienceBottle` -> `.throwableitemprojectile.ThrownExperienceBottle` - `ThrownLingeringPotion` -> `.throwableitemprojectile.ThrownLingeringPotion` - `ThrownSplashPotion` -> `.throwableitemprojectile.ThrownSplashPotion` - `ThrownTrident` -> `.arrow.ThrownTrident` - `WitherSkull` -> `.hurtingprojectile.WitherSkull` - `net.minecraft.world.entity.projectile.windcharge.*` -> `.projectile.hurtingprojectile.windcharge.*` - `net.minecraft.world.entity.vehicle` - `AbstractBoat` -> `.boat.AbstractBoat` - `AbstractChestBoat` -> `.boat.AbstractChestBoat` - `AbstractMinecart` -> `.minecart.AbstractMinecart` - `AbstractMinecartContainer` -> `.minecart.AbstractMinecartContainer` - `Boat` -> `.boat.Boat` - `ChestBoat` -> `.boat.ChestBoat` - `ChestRaft` -> `.boat.ChestRaft` - `Minecart` -> `.minecart.Minecart` - `MinecartBehavior` -> `.minecart.MinecartBehavior` - `MinecartChest` -> `.minecart.MinecartChest` - `MinecartCommandBlock` -> `.minecart.MinecartCommandBlock` - `MinecartFurnace` -> `.minecart.MinecartFurnace` - `MinecartHopper` -> `.minecart.MinecartHopper` - `MinecartSpawner` -> `.minecart.MinecartSpawner` - `MinecartTNT` -> `.minecart.MinecartTNT` - `NewMinecartBehavior` -> `.minecart.NewMinecartBehavior` - `OldMinecartBehavior` -> `.minecart.OldMinecartBehavior` - `Raft` -> `.boat.Raft` - `net.minecraft.world.level.gamerules.GameRule#getResourceLocation` -> `getIdentifier` ## 哦,又来了,一次渲染重写 渲染管线的更多部分已被重写,主要集中在采样器、`RenderType` 的创建和 mipmap 上。 ### 采样器的分离 Blaze3d 已将读取纹理数据时的 `AddressMode` 和 `FilterMode` 设置分离到 `GpuSampler` 中。顾名思义,`GpuSampler` 定义了如何从缓冲区(如纹理)采样数据。`GpuSampler` 包含四个方法:`getAddressModeU` / `getAddressModeV` 用于确定采样器在读取 UV 位置时的行为(重复或钳位),`getMinFilter` / `getMagFilter` 用于分别确定如何缩小或放大纹理(最近邻或线性),`getMaxAnisotropy` 用于可用的最大各向异性过滤级别,以及 `getMaxLod` 用于纹理的最大细节级别。 采样器可以通过 `GpuDevice#createSampler` 创建,但除非您想指定大于 `1` 的不同各向异性过滤级别,或者最大细节级别不是 `0` 或 `1000`,否则没有必要。由于只有 32 种可能的组合,原版创建了所有 `GpuSampler` 并将它们存储在一个缓存中,可通过 `RenderSystem#getSamplerCache` 然后 `SamplerCache#getSampler` 访问: ```java // 直接调用 GpuSampler sampler = RenderSystem.getDevice().createSampler( // U 地址模式 AddressMode.CLAMP_TO_EDGE, // V 地址模式 AddressMode.CLAMP_TO_EDGE, // 缩小过滤器 FilterMode.LINEAR, // 放大过滤器 FilterMode.NEAREST, // 最大各向异性过滤级别 // 原版对于等级渲染使用 1、2、4 或 8 4f, // 纹理的最大细节级别 // 原版对于默认使用 0, // 或对于移动对象和上传到图集使用空 optional。 OptionalDouble.of(0.0) ); // 采样器缓存方法 GpuSampler sampler = RenderSystem.getSamplerCache().getSampler( // U 地址模式 AddressMode.CLAMP_TO_EDGE, // V 地址模式 AddressMode.CLAMP_TO_EDGE, // 缩小过滤器 FilterMode.LINEAR, // 放大过滤器 FilterMode.NEAREST, // 是否为最大细节级别使用 1000 或 0 true ); ``` 要使采样器用于纹理,当在渲染通道中绑定纹理时(通过 `RenderPass#bindTexture`),您现在必须指定要使用的采样器以及纹理视图: ```java try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(...)) { // 设置其他参数 pass.bindTexture( // sampler2D 统一变量的名称,通常在片段着色器中 "Sampler0", // 要采样的纹理 ..., // 要使用的采样器 sampler ); // 绘制缓冲区 } ``` 从用户角度来看,设置后处理器没有变化,因为只能选择钳位到边缘的地址模式。 ### `RenderType` 洗牌 创建 `RenderType` 已在一定程度上被重做。虽然先前实现中的大多数功能仍然存在,但它们已更改以匹配新的渲染系统,其中直接 OpenGL 被抽象化,仅通过其定义的管道和 `RenderSystem` 访问。 #### 现有类型 现有类型已从 `RenderType` 移至 `RenderTypes`(例如,`RenderType#solid` -> `RenderTypes#solid`)。 #### 自定义类型 最初,要创建 `RenderType`,您会使用 `RenderStateShard` 构造一个 `$CompositeState`。每个 `RenderStateShard` 将定义在构建某些网格时如何设置和拆除通道,无论是设置纹理、渲染目标、模型变换等。然后,`$CompositeState` 将被构建以供任何需要的渲染应用使用。 新系统将渲染定义拆分为两部分:`RenderSetup` 和我们的 `RenderType`。顾名思义,`RenderSetup` 设置渲染器,以便在绘制到纹理时使用。拆除被完全移除,因为它要么在绘制 `RenderType` 时直接处理,要么使用可以丢弃的新构造的状态。另一方面,`RenderType` 只是一个命名的 `RenderSetup`。它只处理绘制网格数据,并使设置的某些字段公开以供在其他缓冲区实现中使用。多个类型可以具有相同的 `RenderSetup`,因为许多现有类型动态填充采样器使用的纹理和/或对象的轮廓。 可以通过其构建器 `RenderSetup#Builder` 创建 `RenderSetup`,提供要使用的 `RenderPipeline`。一旦设置了构建器属性,就可以通过 `RenderSetup$RenderSetupBuilder#createRenderSetup` 创建实际的设置: ```java public static final RenderSetup EXAMPLE_SETUP = RenderSetup.builder( // 要使用的管线。 // 这可能会影响设置允许哪些设置。 RenderPipelines.ITEM_ENTITY_TRANSLUCENT_CULL ) // 指定要绑定到提供的采样器的纹理。 // 采样器必须由管线通过 `RenderPipeline$Builder#withSampler` 定义。 // 纹理表示为绝对位置。 .withTexture( // 'Sampler0' 由管线定义。 "Sampler0", // 指向 'assets/minecraft/entity/wolf/wolf_armor_crackiness_low.png'。 Identifier.withDefaultNamespace("textures/entity/wolf/wolf_armor_crackiness_low.png"), // 一个可选的提供的 `GpuSampler`,用于对纹理进行采样。 // 返回的值将在第一次解析后被缓存。 () -> RenderSystem.getSamplerCache().getClampToEdge(FilterMode.NEAREST) ) // 设置后,允许管线使用光照纹理。 // 'Sampler2' 必须由管线通过 `RenderPipeline$Builder#withSampler` 定义。 .useLightmap() // 设置后,允许管线使用覆盖纹理。 // 'Sampler1' 必须由管线通过 `RenderPipeline$Builder#withSampler` 定义。 .useOverlay() // 设置后,使用 `RenderTypes#crumbling` 根据实体模型的破坏进度叠加方块破坏阶段。 // 这仅在 `ModelFeatureRenderer` 中实现。 .affectsCrumbling() // 设置后,根据 `RenderSystem#getProjectionType` 中设置的 `ProjectionType` 对四边形进行排序。 // 这仅在从 `MultiBufferSource$BufferSource` 获取缓冲区时实现。 .sortOnUpload() // 设置使用的缓冲区的初始容量。 // 这仅在 `RenderBuffers` 中构造初始缓冲区时使用。 // 所有自定义的源应用都已经有一些具有确定大小的缓冲区。 .bufferSize(786432) // 一个对象包装的消费者,用于变换模型视图矩阵。 // 原版实现在 `LayeringTransform` 中,通过投影类型应用变换: // - `NO_LAYERING`: 不执行任何操作。 // - `VIEW_OFFSET_Z_LAYERING`: 根据其 `ProjectionType` 将 Z 偏移 1 // - `VIEW_OFFSET_Z_LAYERING_FORWARD`: 根据其 `ProjectionType` 将 Z 偏移 -11 .setLayeringTransform( // 我们也可以构造一个新的变换 new LayeringTransform( // 变换的名称 "examplemod:example_layer", // 变换不应推入或弹出堆栈 // 仅平移、缩放或旋转 stack -> stack.translate(0f, 0.1f, 0f) ) ) // 设置此设置应写入的输出目标, // 除非被 `RenderSystem#output*Override` 纹理覆盖。 // 这通常是主目标,尽管它可以是其他原版目标, // 或者如果您计划处理它,也可以是自定义目标。 .setOutputTarget(OutputTarget.MAIN_TARGET) // 一个对象包装的供应商,提供纹理矩阵。 // 这通常用于在片段着色器中采样之前修改顶点着色器中的纹理 UV 坐标。 // 原版仅将此用于闪光效果和旋风人/能量效果: // - `DEFAULT_TEXTURING`: 不执行任何操作。 // - `GLINT_TEXTURING`: 根据闪光速度平移,旋转 pi/18,并按 8 缩放。 // - `ENTITY_GLINT_TEXTURING`: 根据闪光速度平移,旋转 pi/18,并按 0.5 缩放。 // - `ARMOR_ENTITY_GLINT_TEXTURING`: 根据闪光速度平移,旋转 pi/18,并按 0.16 缩放。 // - `$OffsetTextureTransform`: 按提供的 XY 坐标平移纹理。 .setTextureTransform( // 我们也可以构造一个新的变换 new TextureTransform( // 变换的名称 "examplemod:example_texture", // 要应用于纹理的变换 () -> new Matrix4f().translation(0f, 1f, 0f).scale(1.5f) ) ) // 设置应如何处理网格的轮廓: // - `NONE`: 不执行任何操作。 // - `IS_OUTLINE`: 这是一个轮廓,应写入轮廓缓冲区源。 // - `AFFECTS_OUTLINE`: 这定义了轮廓的形状,应使用 `RenderTypes#OUTLINE` 绘制它。 // 在写入轮廓缓冲区源时检查, // 或者如果功能的轮廓颜色不为 0 .setOutline(RenderSetup.OutlineProperty.AFFECTS_OUTLINE) // 构建用于渲染类型的设置。 .createRenderSetup(); ``` 然后,可以通过 `create` 创建 `RenderType`。 ```java public static final RenderType EXAMPLE_TYPE = RenderType.create( // 用于调试的类型名称 "examplemod:example_type", // 要使用的渲染设置 EXAMPLE_SETUP ); ``` 可以使用 `RenderType#draw` 将 `MeshData` 写入输出目标。 ### Mipmap 策略元数据 纹理的 `mcmeta` 现在可以在 `textures` 部分中指定要使用的 `mipmap_strategy`。有四种可用的策略,`auto` 在没有透明度时默认为 `mean`,在有透明度时默认为 `cutout`。 | 策略 | 描述 | |:---------------:|:--------------------------------------------------------------------------------------------------------------------------| | `mean` | 默认策略,对当前 mipmap 级别的四个像素之间的颜色进行平均。 | | `cutout` | 与 `mean` 相同,但所有级别都是从原始纹理生成的,使用 0.2 的阈值将 alpha 捕捉到 0 或 1。 | | `strict_cutout` | 与 `cutout` 相同,但使用 `0.6` 的阈值设置 alpha 捕捉。 | | `dark_cutout` | 与 `mean` 相同,但仅当周围像素的 alpha 不为 `0` 时才将其包含在平均值中。 | ```json5 // 在 `assets/examplemod/textures/block/example/example_block.png.mcmeta { "texture": { // 使用选定的策略 "mipmap_strategy": "cutout", // 确定在判断像素是完全不透明还是完全透明时, // 截止值应偏置多少。 // 较大的数字意味着更高的 alpha 截止值, // 而较低的值使用较低的 alpha 截止值。 "alpha_cutoff_bias": 0.2 } } ``` ### 方块和地形拆分 由独立方块和地形使用的 `RenderPipeline` 已被拆分为单独的管线:分别带有前缀 `_BLOCK` 和 `_TERRAIN`。这包括实体、切割、半透明和绊线管线。半透明管线没有方块变体。 ### 物品图集 方块图集不再包含专门用于物品的纹理。这些已移至它们自己的图集,名为 `minecraft:items`,其 id 存储在 `AtlasIds#ITEMS`。 如果给定的 `Material` 可以同时使用方块和物品纹理,则应使用 `ModelManager#BLOCK_OR_ITEM` 特殊情况提供。 - `com.mojang.blaze3d.buffers` - `GpuBuffer`,`size` 现在使用 `long` 作为大小 - `slice` 现在使用 `long` 作为长度和偏移 - `GpuBufferSlice` 现在使用 `long` 作为长度和偏移 - `com.mojang.blaze3d.opengl` - `BufferStorage` - `createBuffer` 现在使用 `long` 作为大小 - `mapBuffer` 现在使用 `long` 作为长度和偏移 - `DirectStateAccess` - `bufferSubData` 现在使用 `long` 作为偏移 - `mapBufferRange`、`flushMappedBufferRange`、`copyBufferSubData` 现在使用 `long` 作为长度和偏移 - `GlBuffer` 现在使用 `long` 作为大小 - `GlDevice` 现在接受 `ShaderSource` 而不是 `BiFunction` - `getOrCompileShader` 现在接受 `ShaderSource` 而不是 `BiFunction` - `GlRenderPass` - `samplers` 现在是一个字符串到 `GlRenderPass$TextureViewAndSampler` 的哈希映射 - `$TextureViewAndSampler` - 一个记录,定义了一个采样器及其采样的纹理。 - `GlSampler` - GPU 采样器的 OpenGL 实现。 - `GlStateManager` - `_glBufferSubData` 现在使用 `long` 作为偏移 - `_glMapBufferRange` 现在使用 `long` 作为长度和偏移 - `GlTexture#modesDirty`、`flushModeChanges` 已移除 - `GlTextureView#getFbo` - 获取纹理的帧缓冲区对象,如果存在则使用缓存。 - `com.mojang.blaze3d.pipeline.RenderTarget#filterMode`、`setFilterMode` 已移除 - `com.mojang.blaze3d.platform.TextureUtil` - `solidify` - 通过打包和解包像素来修改纹理,以更好地帮助 mipmap 内的非暗化内部。 - `fillEmptyAreasWithDarkColor` - 将空像素设置为一个 RGB 值为图像中最暗颜色的空像素。 - `com.mojang.blaze3d.shaders.ShaderSource` - 一个函数式接口,从其 id 和类型以字符串形式获取着色器源。 - `com.mojang.blaze3d.systems` - `CommandEncoder#copyTextureToBuffer` 现在使用 `long` 作为偏移 - `GpuDevice` - `createSampler` - 为某个源到目标创建一个采样器,具有所需的地址和过滤模式。 - `precompilePipeline` 现在接受 `ShaderSource` 而不是 `BiFunction` - `getMaxSupportedAnisotropy` - 硬件支持的最大各向异性过滤级别。 - `createBuffer` 现在使用 `long` 作为大小 - `RenderPass#bindTexture` 现在接受 `GpuSampler` - `RenderSystem` 现在使用 `long` 作为大小 - `samplerCache` - 返回一个包含所有可能组合的采样器缓存。 - `TEXTURE_COUNT` 已移除 - `setupOverlayColor`、`teardownOverlayColor` 已移除 - `setShaderTexture`、`getShaderTexture` 已移除 - `setTextureMatrix`、`resetTextureMatrix`、`getTextureMatrix` 已移除 - `lineWidth` -> `VertexConsumer#setLineWidth` - `getShaderLineWidth` -> `Window#getAppropriateLineWidth` - `initRenderer` 现在接受 `ShaderSource` 而不是 `BiFunction` - `SamplerCache` - 一个缓存,包含渲染器可能使用的所有采样器。 - `com.mojang.blaze3d.textures` - `GpuSampler` - 一个具有指定 UV 地址模式和缩小及放大过滤器的缓冲区采样器。 - `GpuTexture` - `addressModeU` -> `GpuSampler#getAddressModeU` - `addressModeV` -> `GpuSampler#getAddressModeV` - `minFilter` -> `GpuSampler#getMinFilter` - `magFilter` -> `GpuSampler#getMagFilter` - `setAddressMode`、`setTextureFilter` 已被 `SamplerCache#getSampler` 取代,不是一对一 - `useMipmaps`、`setUseMipmaps` 已移除 - `net.minecraft.client` - `Options#textureFiltering` - 从一定角度或远处观看时选择的纹理采样方法。 - `TextureFilteringMethod` - 从一定角度或远处观看纹理时的采样方法。 - `net.minecraft.client.gui.render.TextureSetup` 现在接受每个纹理的 `GpuSampler` - 这也包括静态构造函数 - `net.minecraft.client.particle.SingleQuadParticle$Layer#ITEMS` - 用于具有物品纹理的粒子的层。 - `net.minecraft.client.renderer` - `FaceInfo` - `$Constants` -> `$Extent` - `$VertexInfo` 现在是一个记录 - `ItemBlockRenderTypes#getRenderType(ItemStack)` - `LightTexture#turnOffLightLayer`、`turnOnLightLayer` 已移除 - `LevelRenderer#resetSampler` - 重置区块层采样器。 - `PostPass` - `$Input#bilinear` - 是否使用双线性过滤器。 - `$TextureInput` 现在接受一个 `boolean`,表示是否使用双线性过滤器 - `RenderPipelines` - `SOLID` -> `SOLID_BLOCK`、`SOLID_TERRAIN` - `CUTOUT` -> `CUTOUT_BLOCK`、`CUTOUT_TERRAIN` - `CUTOUT_MIPPED` 已移除 - `TRANSLUCENT` -> `TRANSLUCENT_TERRAIN` - `TRIPWIRE` -> `TRIPWIRE_BLOCK`、`TRIPWIRE_TERRAIN` - `ANIMATE_SPRITE_SNIPPET`、`ANIMATE_SPRITE_BLIT`、`ANIMATE_SPRITE_INTERPOLATION` - 用于动画精灵的管线。 - `RenderStateShard` 已被 `RenderSetup` 取代,不是一对一 - `$LightmapStateShard` -> `RenderSetup#useLightmap` - `$OverlayStateShard` -> `RenderSetup#useOverlay` - `$MultiTextureStateShard`、`$TextureStateShard` -> `RenderSetup#textures` - `$LayeringStateShard` -> `RenderSetup#layeringTransform`、`LayeringTransform` - `$LineStateShard` -> `VertexConsumer#setLineWidth` - `$OutputStateShard` -> `RenderSetup#outputTarget`、`OutputTarget` - `$TexturingStateShard`、`$OffsetTexturingStateShard` -> `RenderSetup#textureTransform`、`TextureTransform` - `RenderType` 已被拆分为两个独立的概念,不是一对一 - 所有存储的 `RenderType` 已移至 `RenderTypes` - 实际的类用法已移至 `.rendertype.RenderType`,在那里它执行 `$CompositeRenderType` 的工作 - `Sheets#translucentBlockItemSheet` - 用于半透明方块物品的渲染类型。 - `net.minecraft.client.renderer.block` - `BlockRenderDispatcher` 不再接受提供的 `SpecialBlockModelRenderer` - `LiquidBlockRenderer` 现在接受 `MaterialSet` - `setupSprites` 已移至 `LiquidBlockRenderer` 构造函数中 - `net.minecraft.client.renderer.block.model` - `BakedQuad` - `vertices` -> `position*`、`packedUV*`,不是一对一 - `position` - 根据索引获取位置向量。 - `packedUV` - 根据索引获取打包的 UV。 - `BlockElementRotation` 现在接受 `Vector3fc` 作为原点,以及 `Matrix4fc` 变换 - 构造函数也接受 `$RotationValue` 而不是 `Direction$Axis` 和角度 `float` - `$EulerXYZRotation` - 以度为单位的 XYZ 旋转。 - `$RotationValue` - 一个定义旋转变换的接口。 - `$SingleAxisRotation` - 围绕单个轴以度为单位的旋转。 - `FaceBakery` - `VERTEX_COUNT` -> `BakedQuad#VERTEX_COUNT` - `VERTEX_INT_SIZE`、`COLOR_INDEX`、`UV_INDEX` 已移除 - `bakeQuad` 现在接受 `ModelBaker$PartCache` - `extractPositions` 已移除 - `SimpleModelWrapper#bake` 现在返回 `BlockModelPart` - `SimpleUnbakedGeometry#bake` 现在接受 `ModelBaker` 而不是 `SpriteGetter` - `TextureSlots$parseTextureMap` 不再接受 `Identifier` - `Variant` - `withZRot` - 围绕 Z 轴旋转模型状态。 - `$SimpleModelState` 现在接受一个 Z `Quadrant` - `withZ` - 设置模型状态的 Z 象限。 - `VariantMutator#Z_ROT` - 围绕 Z 轴旋转模型。 - `net.minecraft.client.renderer.chunk` - `ChunkSectionLayer` 不再接受是否使用 mipmap - `CUTOUT_MIPPED` 已移除 - `texture` 已移除 - `ChunkSectionsToRender` 现在接受 `GpuTextureView` - `dynamicTransforms` -> `chunkSectionInfos` - `renderGroup` 现在接受 `GpuSampler` - `net.minecraft.client.renderer.item` - `BlockModelWrapper` 构造函数现在是包私有的 - `computeExtents` 现在返回 `Vector3fc` 的数组 - `ItemStackRenderState$LayerRenderState` - `NO_EXTENTS_SUPPLIER` 现在是一个提供的 `Vector3fc` 数组 - `setExtents` 现在接受一个提供的 `Vector3fc` 数组 - `net.minecraft.client.renderer.rendertype.RenderTypes` - `MOVING_BLOCK_SAMPLER` - 用于移动中方块的采样器。 - `solid` -> `solidMovingBlock` - `cutout` -> `cutoutMovingBlock` - `tripwire` -> `tripwireMovingBlock` - `net.minecraft.client.renderer.texture` - `AbstractTexture#setUseMipmaps` 已移除 - `MipmapGenerator#generateMipLevels` 现在接受纹理的名称、一个 `MipmapStrategy` 来确定特定纹理应如何进行 mipmap,以及一个用于 alpha 截止偏置的 `float` - `MipmapStrategy` - 一个枚举,定义了在为纹理构造 mipmap 时使用的策略。 - `OverlayTexture#setupOverlayColor`、`teardownOverlayColor` 被 `getTextureView` 取代,不是一对一 - `SpriteContents` 现在接受一个可选的 `TextureMetadataSection` 来确定精灵的元数据 - `UBO_SIZE` - 精灵内容的统一缓冲区对象大小。 - `createTicker` -> `createAnimationState`,不是一对一 - `uploadFirstFrame` 不再接受纹理 `int`,而是接受一个 mip 级别 `int` - `$AnimatedTexture#createTicker`、`uploadFirstFrame` -> `createAnimationState`,不是一对一 - `$Ticker` -> `$AnimationState`,不是一对一 - `tickAndUpload` -> `tick`、`getDrawUbo`、`needsToDraw`、`drawToAtlas`;不是一对一 - `SpriteTicker` 接口已移除 - `Stitcher` 现在接受各向异性过滤级别 - `$Holder(T, int)` 已移除 - `$Region#walk` 现在接受一个填充 `int` - `$SpriteLoader` 不再接受最小宽度/高度 - `load` 现在接受一个填充 `int` - `TextureAtlas` 现在实现 `TickableTexture` 而不是 `Tickable` - `TextureAtlasSprite` 现在实现 `AutoCloseable` - 构造函数接受一个填充 `int` - `createTicker` -> `createAnimationState`,不是一对一 - `getUOffset`、`getVOffset`、`uvShrinkRatio` 已移除 - `uploadFirstFrame` 现在接受 mip 级别 `int` - `uploadSpriteUbo` - 将图集精灵上传到缓冲区。 - `$Ticker` 接口已移除 - `TextureManager` 不再实现 `Tickable` - `Tickable` -> `TickableTexture` - `net.minecraft.client.renderer.texture.atlas` - `SpriteSource$SpriteSupplier` -> `$DiscardableLoader` - `Function` 超接口现在表示为 `$Loader` - `apply` -> `get` - `SpriteSourceList#list` 现在返回一个 `SpriteSource$Loader` 列表 - `net.minecraft.client.resources.metadata.texture.TextureMetadataSection` 现在接受一个 `MipmapStrategy` 来确定特定纹理应如何进行 mipmap,以及一个用于 alpha 截止偏置的 `float` - `net.minecraft.client.resources.model` - `ModelBaker` - `missingBlockModelPart` - 缺失的方块模型。 - `parts` - 先前构造的向量的缓存。 - `$PartCache` - 一个缓存,用于内部存储四边形中先前构造的顶点。 - `ModelBakery` - `*_STILL` - 流体的静态纹理位置。 - `$MissingModels` 现在接受一个 `BlockModelPart` 缺失模型 - `ModelManager` - `BLOCK_OR_ITEM` - 一个特殊情况,导致模型管理器同时检查物品和方块图集。 - `specialBlockModelRenderer` 现在返回原始渲染器而不是提供的值。 - `net.minecraft.data.AtlasIds#ITEMS` - 物品图集标识符。 - `net.minecraft.world.level.block.LeavesBlock#setCutoutLeaves` - 设置树叶是否使用切割渲染。 ## Gizmo 控件 Gizmo 是提交和渲染解耦的最新迭代,这次用于调试渲染器。然而,提交 gizmo 进行渲染的底层结构要复杂得多,因为调试渲染器几乎可以在客户端进程的任何时刻提交对象。 ### 什么是 Gizmo? 一个 `Gizmo` 基本上是一个对象,它提交一些对象图元——特别是点、线、三角形扇、四边形和文本——进行渲染。每个 gizmo 通过 `emit` 将这些图元串在一起形成所需的形状。在渲染过程中,它们使用 `RenderPipelines#DEBUG_*` 管线将其图元渲染到屏幕。创建一个新的 gizmo 就像扩展接口一样简单: ```java // 存储一些参数,如渲染状态,以提交元素图元 public record ExampleGizmo(Vec3 start, Vec3 end) implements Gizmo { @Override public void emit(GizmoPrimitives gizmos, float alphaMultiplier) { // 在此处提交任何元素 gizmos.addLine(this.start, this.end, ARGB.multiplyAlpha(0, alphaMultiplier), 3f); } } ``` 实际提交元素通过 `Gizmos#addGizmo` 发生。这会将 gizmo 存储起来,以便在 `Minecraft#tick` 或客户端上的任何渲染期间发出并绘制到屏幕——这也是调试渲染器发出 gizmo 的方式,在单机世界中通过 `IntegratedServer#tickServer`,或通过任一侧的数据包处理。`Gizmos` 中的所有方法都在内部调用 `addGizmo`,这就是为什么该方法通常在其类之外不存在的原因: ```java // 在 GameRenderer#render 的某处 Gizmos.addGizmo(new ExampleGizmo(Vec3.ZERO, Vec3.X_AXIS)); // 内部调用 addGizmo Gizmos.point(Vec3.ZERO, 0, 5f); ``` 调用 `addGizmo` 返回一个 `GizmoProperties`,它在绘制元素时设置一些属性,假设 `GizmoCollector` 不是 `NOOP`。`GizmoProperties` 提供了三个方法: | 方法 | 描述 | |:------------------:|:---------------------------------------------------------------------------| | `setAlwaysOnTop` | 在渲染前清除深度纹理。 | | `persistForMillis` | 在消失前将 gizmo 在屏幕上保持指定的时间。 | | `fadeOut` | 当持续一定时间后,使消失过程淡出。 | ### 组合在一起 那么,您如何几乎在客户端管道的任何地方提交 gizmo 进行渲染?这一切都从 `Gizmos#withCollector` 和 `SimpleGizmoCollector` 开始。 `SimpleGizmoCollector` 基本上只是一个保存收集到的要渲染的 gizmo 的列表。在渲染过程中,调用 `SimpleGizmoCollector#drainGizmos`,将 gizmo 复制到一个单独的列表中,供渲染器通过熟悉的帧通道和缓冲区源在 `Gizmo#emit` 之前使用。然后,`drainGizmos` 根据 `GizmoProperties#persistForMillis` 清除内部列表,如果未指定则立即清除,以供下一帧使用。 为了实际收集这些元素,有一个相当复杂的过程。`Minecraft`、`LevelRenderer` 和 `IntegratedServer` 都有自己的 `SimpleGizmoCollector`。这是通过使用 `Gizmo#withCollector` 设置收集器来完成的,它返回一个 `Gizmos$TemporaryCollection`。该集合是 `AutoCloseable` 的,当关闭时,会释放本地线程上持有的收集器。因此,收集器被包装在 try-with-resources 中,以便在这些期间促进提交。然后,在调试通道期间,每Tick的 gizmo 与每帧的 gizmo 合并,并通过 `addTemporaryGizmos` 绘制到屏幕上,实际上是在 `LevelRenderer#renderLevel` 的最后一刻。在单机世界中,`IntegratedServer` 的 gizmo 存储在一个易失性字段中,允许从客户端线程访问它。 - `net.minecraft.client.Minecraft` - `collectPerTickGizmos` - 返回所有要发出的 gizmo 的集合。 - `getPerTickGizmos` - 获取要绘制到屏幕的 gizmo。 - `net.minecraft.client.renderer` - `LevelRenderer#collectPerFrameGizmos` - 返回所有要发出的 gizmo 的集合。 - `OrderedSubmitNodeCollector#submitHitbox` 已移除 - `ShapeRenderer` - `renderShape` 现在接受一个线宽 `float` - `renderLineBox` -> `Gizmos#cuboid`,不是一对一 - `addChainedFilledBoxVertices` -> `Gizmos#cuboid`,不是一对一 - `renderFace` -> `Gizmos#rect`,不是一对一 - `renderVector` -> `Gizmos#line`,不是一对一 - `SubmitNodeCollection#getHitboxSubmits` 已移除 - `SubmitNodeStorage$HitboxSubmit` 记录已移除 - `net.minecraft.client.renderer.debug` - `DebugRenderer` - `render` -> `emitGizmos`,不再接受 `PoseStack`、`BufferSource` 或 `boolean`,现在接受部分刻 `float` - `renderFilledUnitCube` -> `Gizmos#cuboid`,不是一对一 - `renderFilledBox` -> `Gizmos#cuboid`,不是一对一 - `renderTextOverBlock` -> `Gizmos#billboardTextOverBlock`,不是一对一 - `renderTextOverMob` -> `Gizmos#billboardTextOverMob`,不是一对一 - `renderFloatingText` -> `Gizmos#billboardText`,不是一对一 - `renderVoxelShape` -> `LevelRenderer#renderHitOutline`,现在是私有的,不是一对一 - `SimpleDebugRenderer$render` -> `emitGizmos`,不再接受 `PoseStack`、`BufferSource` 或 `boolean`,现在接受部分刻 `float` - `GameTestBlockHighlightRenderer` - `render` -> `emitGizmos`,不接受参数 - `renderMarker` 不再接受 `PoseStack` 或缓冲区源 - `$Marker#get*` 已移除 - `LightDebugRenderer` 现在接受两个标志,决定是否显示块光或天空光 - `PathfindingRenderer#renderPath`、`renderPathLine` 不再接受 `PoseStack` 或缓冲区源 - `net.minecraft.client.renderer.entity.EntityRenderer#extractAdditionalHitboxes` 已移除 - `net.minecraft.client.renderer.entity.state` - `EntityRenderState#hitboxesRenderState`、`serverHitboxesRenderState` 已移除 - `HitboxesRenderState` 类已移除 - `ServerHitboxesRenderState` 类已移除 - `net.minecraft.client.renderer.feature.HitboxFeatureRenderer` -> `EntityHitboxDebugRenderer`,不是一对一 - `net.minecraft.client.renderer.gizmos.DrawableGizmoPrimitives` - 用于图元形状或 gizmo 的存储和渲染器。 - `net.minecraft.client.renderer.texture` - `AbstractTexture` - `sampler`、`getSampler` - 返回纹理使用的 `GpuSampler`。 - `setClamp` -> `GpuSampler#getAddressMode*`,不是一对一 - `setFilter` -> `GpuSampler#get*Filter`,不是一对一 - `ReloadableTexture` 不再接受地址模式和过滤 `boolean` - `net.minecraft.client.server.IntegratedServer#getPerTickGizmos` - 获取当前Tick要绘制到屏幕的 gizmo。 - `net.minecraft.gizmos` - `ArrowGizmo` - 一个绘制箭头的 gizmo。 - `CircleGizmo` - 一个绘制近似圆形(使用二十个顶点)的 gizmo。 - `CuboidGizmo` - 一个绘制矩形棱柱的 gizmo。 - `Gizmo` - 一个可以发出简单形状图元进行绘制的对象。 - `GizmoCollector` - 一个只添加的收集器。 - `GizmoPrimitives` - 可以绘制的形状图元。 - `GizmoProperties` - 应用于 gizmo 应如何绘制的属性。 - `Gizmos` - 一个用于创建 gizmo 和收集它们的静态方法集合。 - `GizmoStyle` - 一个属性持有者,用于定义 gizmo 应如何绘制。这些由 gizmo 本身使用,而不是实际图元。 - `LineGizmo` - 一个绘制线的 gizmo。 - `PointGizmo` - 一个绘制点的 gizmo。 - `RectGizmo` - 一个绘制矩形的 gizmo。 - `SimpleGizmoCollector` - 一个收集器实现,用于在将 gizmo 发送到渲染之前添加它们。 - `TextGizmo` - 一个绘制文本的 gizmo。 - `net.minecraft.server.MinecraftServer#processPacketsAndTick` - 处理服务器Tick和数据包处理。 ## 权限大修 权限级别整数已被扩展为一个既简单又复杂的新系统。有三个主要部分:`Permission`、`PermissionSet` 和 `PermissionCheck`。 ### 权限 `Permission` 在功能上是定义某种状态的数据对象。原版提供了两种类型的权限:`Permission$Atom`,它只是一个唯一的单元对象;以及 `Permission$HasCommandLevel`,它持有命令所需的 `PermissionLevel`。这两个数据对象都注册为映射编解码器,用于转储命令报告。 ```java // 尝试查询管理员级别权限。 public static final Permission COMMANDS_MODERATOR = new Permission.HasCommandLevel(PermissionLevel.MODERATORS); ``` 可以通过某个扩展 `Permission` 的类或记录来创建自定义权限,并将关联的 `MapCodec` 注册到其静态注册表: ```java // 这不检查用户是否具有给定的权限 // 它仅仅只是持有表示权限状态的数据 public record HasExamplePermission(int state) implements Permission { public static final MapCodec MAP_CODEC = Codec.INT.fieldOf("state") .xmap(HasExamplePermission::new, HasExamplePermission::state); @Override public MapCodec codec() { return HasExamplePermission.MAP_CODEC; } } // 在某个注册处理程序中 Registry.register( BuiltInRegistries.PERMISSION_TYPE Identifier.withNamespaceAndPath("examplemod", "has_example_permission"), HasExamplePermission.MAP_CODEC ); // 存储权限以供使用 public static final Permission HAS_STATE_ONE = new HasExamplePermission(1); ``` ### 权限集 如果 `Permission` 定义了可查询的状态,那么 `PermissionSet` 就是用户实际拥有的权限。`PermissionSet` 是一个函数式接口,用于检查用户是否具有所需的状态(通过 `hasPermission`)。原版使用 `LevelBasedPermissionSet` 来检查查询的权限是否与当前的 `PermissionLevel` 匹配。由于通常会对一组权限检查权限集,因此可以通过 `PermissionSet#union` 将多个权限集组合成一个。它在功能上执行 OR 操作,意味着如果一个集合不检查某个权限,它应默认为 `false`。 ```java public interface ExamplePermissionSet extends PermissionSet { // 为我们的权限跟踪用户的状态 int state(); @Override default boolean hasPermission(Permission permission) { // 检查我们的权限 if (permission instanceof HasExamplePermission example) { return this.state() >= example.state(); } // 否则忽略 return false; } } // 存储一个权限集 // 也可以在所需的目标上实现或存储 public static ExamplePermissionSet STATE_ONE = () -> 1; // 检查权限集是否具有所需的权限 STATE_ONE.hasPermission(HAS_STATE_ONE); ``` 目前,没有简单的方法在所需用户上存储自定义权限集。`CommandSourceStack` 确实有一个通过 `withMaximumPermission` 合并其他权限集的方法,但这需要在关联的 `createCommandSourceStack` 方法中处理。通常可以通过 `permissions` 方法查询普通的 `LevelBasedPermissionSet`,尽管对象之间没有公共接口,即使 `PermissionSetSupplier` 似乎为此目的而存在。 ### 权限检查 现在,`PermissionSet` 永远不会直接在代码库中检查 `Permission`。这需要对象始终可访问。相反,会创建一个 `PermissionCheck` 对象,它接受 `PermissionSet` 并 `check` 用户是否具有继续执行所需的数据。原版提供了两种类型的检查:`$AlwaysPass`,意味着它将始终返回 true;以及 `$Require`,要求集合具有所需的 `Permission`。这些检查也有一个用于转储命令报告的映射编解码器。 ```java // 要求权限集具有管理员命令的访问权限 public static final PermissionCheck LEVEL_MODERATORS = new PermissionCheck.Require(COMMANDS_MODERATOR); ``` 可以通过实现 `check` 的某个类或记录来创建自定义权限检查,并将映射编解码器注册到其静态注册表: ```java public static record AnyOf(List permissions) implements PermissionCheck { public static final MapCodec MAP_CODEC = Permission.CODEC.listOf().fieldOf("permissions") .xmap(AnyOf::new, AnyOf::permissions); @Override public boolean check(PermissionSet permissionSet) { return this.permissions.stream().filter(perm -> permissionSet.hasPermission(perm)).findAny().isPresent(); } @Override public MapCodec codec() { return MAP_CODEC; } } // 在某个注册处理程序中 Registry.register( BuiltInRegistries.PERMISSION_CHECK_TYPE Identifier.withNamespaceAndPath("examplemod", "any_of"), AnyOf.MAP_CODEC ); // 存储检查以供在命令中使用 public static final PermissionCheck CHECK_STATE_ONE = new AnyOf(List.of( HAS_STATE_ONE, Permissions.COMMANDS_GAMEMASTER )); // 对于某个命令 Commands.literal("example").requires(Commands.hasPermission(CHECK_STATE_ONE)); ``` - `net.minecraft.client.multiplayer.ClientSuggestionProvider` 不再实现 `PermissionSource` - 构造函数现在接受 `PermissionSet` 而不是 `boolean` - `allowsRestrictedCommands` -> `ClientPacketListener#ALLOW_RESTRICTED_COMMANDS`,现在是私有的,不是一对一 - `net.minecraft.client.player.LocalPlayer#setPermissionLevel` -> `setPermissions`,不是一对一 - `net.minecraft.commands` - `Commands` - `LEVEL_*` 现在是 `PermissionCheck` 而不是 `int` - `hasPermission` 现在接受 `PermissionCheck` 而不是 `int`,并返回 `PermissionProviderCheck` 而不是 `PermissionCheck` - `createCompilationContext` - 使用给定的权限创建源堆栈。 - `CommandSourceStack` 不再实现 `PermissionSource` - 构造函数现在接受 `PermissionSet` 而不是 `int` - `protected` 构造函数现在是 `private` - `withPermission` 现在接受 `PermissionSet` 而不是 `int` - `withMaximumPermission` 现在接受 `PermissionSet` 而不是 `int` - `ExecutionCommandSource` 现在扩展 `PermissionSetSupplier` 而不是 `PermissionSource` - `PermissionSource` 接口已移除 - `SharedSuggestionProvider` 现在扩展 `PermissionSetSupplier` - `net.minecraft.commands.arguments.selector.EntitySelectorParser#allowSelectors` 现在有一个接受 `PermissionSetSupplier` 的重载 - `net.minecraft.core.registries` - `BuiltInRegistries#PERMISSION_TYPE`、`Registries#PERMISSION_TYPE` - 一个定义某些数据需求的对象。 - `BuiltInRegistries#PERMISSION_CHECK_TYPE`、`Registries#PERMISSION_CHECK_TYPE` - 一个谓词,检查集合是否具有所需的数据。 - `net.minecraft.server` - `MinecraftServer` - `operatorUserPermissionLevel` -> `operatorUserPermissions`,不是一对一 - `getFunctionCompilationLevel` -> `getFunctionCompilationPermissions`,不是一对一 - `getProfilePermissions` 现在返回 `LevelBasedPermissionSet` - `ReloadableServerResources#loadResources` 现在接受 `PermissionSet` 而不是 `int` - `ServerFunctionLibrary` 现在接受 `PermissionSet` 而不是 `int` - `WorldLoader$InitConfig` 现在接受 `PermissionSet` 而不是 `int` - `net.minecraft.server.commands.PermissionCheck` -> `.server.permissions.PermissionCheck`,不是一对一 - `net.minecraft.server.dedicated.DedicatedServerProperties` - `opPermissionLevel` -> `opPermissions`,不是一对一 - `functionPermissionLevel` -> `functionPermissions`,不是一对一 - `deserializePermissions`、`serializePermission` - 读取和写入选定的级别权限集。 - `net.minecraft.server.jsonrpc.internalapi` - `MinecraftOperatorListService#op` 现在接受一个可选的 `PermissionLevel` 而不是 `int` - `MinecraftServerSettingsService` - `getOperatorUserPermissionLevel` -> `getOperatorUserPermissions`,不是一对一 - `setOperatorUserPermissionLevel` -> `setOperatorUserPermissions`,不是一对一 - `net.minecraft.server.jsonrpc.methods` - `OperatorService$OperatorDto#permissionLevel` 现在接受一个可选的 `PermissionLevel` 而不是 `int` - `ServerSettingsService` - `operatorUserPermissionLevel` 现在返回 `PermissionLevel` 而不是 `int` - `setOperatorUserPermissionLevel` 现在接受并返回 `PermissionLevel` 而不是 `int` - `net.minecraft.server.permissions` - `LevelBasedPermissionSet` - 一组权限,检查用户是否具有相等或更高的命令权限级别。 - `Permission` - 与用户权限相关的数据,例如命令级别。 - `PermissionCheckTypes` - 原版提供的权限检查类型。 - `PermissionLevel` - 定义权限的级别序列。 - `PermissionProviderCheck` - 一个谓词,检查供应商的权限集与检查的匹配。 - `Permissions` - 原版提供的权限。 - `PermissionSet` - 一组用户拥有的权限,但主要定义一个方法来确定用户是否具有所需的权限。 - `PermissionSetSupplier` - 一个提供 `PermissionSet` 的对象。 - `PermissionSetUnion` - 多个权限集的联合。 - `PermissionTypes` - 原版提供的权限类型。 - `net.minecraft.server.players` - `PlayersList#op` 现在接受一个可选的 `LevelBasedPermissionSet` 而不是 `int` - `ServerOpListEntry` 现在接受 `LevelBasedPermissionSet` 而不是 `int` - `getLevel` -> `permissions`,不是一对一 - `net.minecraft.world.entity.player.Player#getPermissionLevel`、`hasPermissions` -> `permissions`,不是一对一 - `net.minecraft.world.entity.projectile.ProjectileUtils` - `getHitEntitiesAlong` - 获取沿提供路径击中的实体。 - `getManyEntityHitResult` - 获取沿两点之间路径在边界框内击中的所有实体。 - `net.minecraft.world.entity.projectile.arrow.AbstractArrow#findHitEntities` - 获取被向量击中的所有实体。 ## 新数据组件 随着矛的加入,添加了许多数据组件以提供相关功能。以下是对这些组件的简要概述。 ### 使用效果 `DataComponents#USE_EFFECTS` 定义了一些效果,应用于正在使用(例如,右键单击)物品的玩家。目前,只有三种类型的效果:玩家在使用物品时是否可以冲刺、使用交互是否引起振动,以及应用于玩家水平移动的标量。 ```java // 对于某个物品注册 new Item(new Item.Properties.component( DataComponents.USE_EFFECTS, new UseEffects( // 玩家在使用物品时是否可以冲刺 true, // 是否在物品使用时从玩家处发送振动 false // 应用于玩家水平移动的标量 0.5f ) )); ``` ### 伤害类型 `DataComponents#DAMAGE_TYPE` 定义了用此物品击中实体时应用于实体的伤害类型。它接受伤害类型的 `ResourceKey` 或 `DamageType` 对象本身。 ```java // 对于某个物品注册 new Item(new Item.Properties.component( DataComponents.DAMAGE_TYPE, new EitherHolder<>( // 此物品对攻击实体施加的伤害类型 DamageTypes.FALLING_ANVIL ) )); ``` ### 挥动动画 `DataComponents#SWING_ANIMATION` 定义了使用物品挥动或攻击(例如,左键单击)时播放的动画。有三种类型的动画可以播放:`SwingAnimationType#NONE`,什么都不做;`WHACK`,播放标准的挥动动画;以及 `STAB`,播放矛的刺击动画。也可以指定动画的长度。 ```java // 对于某个物品注册 new Item(new Item.Properties.component( DataComponents.SWING_ANIMATION, new SwingAnimation( // 要播放的动画 SwingAnimationType.NONE, // 播放动画的时间,以刻为单位 20 ) )); ``` ### 最小攻击充能 `DataComponents#MINIMUM_ATTACK_CHARGE` 决定玩家在使用该物品进行另一次攻击之前必须等待多长时间。充能值介于 0 和 1 之间,决定了在另一次攻击之前等待延迟的百分比。延迟由玩家的攻击速度决定。如果玩家的动作是刺击,则检查两次。 ```java // 对于某个物品注册 new Item(new Item.Properties.component( DataComponents.MINIMUM_ATTACK_CHARGE, // 玩家在使用此物品进行另一次攻击之前必须等待的时间百分比 0.5f )); ``` ### 攻击范围 `DataComponents#ATTACK_RANGE` 决定了当实体使用此物品攻击另一个实体时,可以攻击的范围。如果未设置,则默认为实体的交互范围属性。指定的范围适用于玩家,生物的攻击范围由范围乘以生物因子决定。当玩家处于创造模式时,也可以指定一个范围,覆盖默认范围。 ```java // 对于某个物品注册 new Item(new Item.Properties.component( DataComponents.ATTACK_RANGE, new AttackRange( // 此物品击中实体的最小范围(以方块为单位)。 // 必须在 [0, 64] 之间;默认为 0。 0.4f, // 此物品击中实体的最大范围(以方块为单位)。 // 必须在 [0,64] 之间;默认为 3。 4.5f, // 此物品击中实体的最小范围(以方块为单位), // 前提是持有实体是处于创造模式的玩家。 // 这取代了最小范围。 // 必须在 [0, 64] 之间;默认为 0。 0f, // 此物品击中实体的最大范围(以方块为单位), // 前提是持有实体是处于创造模式的玩家。 // 这取代了最大范围。 // 必须在 [0,64] 之间;默认为 3。 5f, // 用于膨胀碰撞箱的边距(以方块为单位), // 补偿潜在的精度问题。 // 必须在 [0,1] 之间;默认为 0.3。 0.25f, // 乘以最小和最大范围的标量,以确定 // 非玩家实体的触及范围。 // 必须在 [0,2] 之间;默认为 1。 1.1f ) )); ``` ### 穿刺武器 `DataComponents#PIERCING_WEAPON` 将玩家的攻击设置为不是攻击,而是刺击或穿刺攻击。这是一个与挥动不同的动作,后者要么攻击实体,要么破坏方块。穿刺武器可以攻击实体,但无法破坏方块。它也会对冲刺应用任何附魔效果。穿刺武器仅适用于玩家。 逻辑流程如下: - 如果 `Player#cannotAttackWithItem` 返回 true,则终止流程 - 穿刺攻击通过以下方式处理: - 客户端 - `MultiPlayerGameMode#piercingAttack` - 服务器 - `PiercingWeapon#attack` - 仅限服务器: - 获取所有满足以下条件的实体: - 在实体的攻击范围内 `DataComponents#ATTACK_RANGE` - 在从玩家眼睛位置开始构建的碰撞箱内 - 如果 `PiercingWeapon#canHitEntity` 返回 true: - 玩家不是无敌或死亡,并且 - 要么: - 实体是 `Interaction` 实体 - 或者: - 实体可以被投射物击中 - 如果双方都是玩家,则此玩家可以伤害对方玩家 - 不是同一载具的乘客 - 对每个实体调用 `LivingEntity#stabAttack` - 触发 `LivingEntity#onAttack` - 触发 `LivingEntity#lungeForwardMaybe` - 仅限服务器: - 如果至少击中了一个实体,则播放 `PiercingWeapon#makeHitSound` - 播放 `PiercingWeapon#makeSound` - 触发 `LivingEntity#swing` ```java // 对于某个物品注册 new Item(new Item.Properties.component( DataComponents.PIERCING_WEAPON, new PiercingWeapon( // 被此物品击中是否会对实体造成击退。 true, // 被此物品击中是否会使实体从载具上下来。 true, // 使用此物品攻击时播放的声音。 // 如果 optional 为空,则不播放声音。 Optional.of(SoundEvents.LLAMA_SWAG), // 此物品击中实体时播放的声音。 // 如果 optional 为空,则不播放声音。 Optional.of(SoundEvents.ITEM_BREAK) ) )); ``` ### 动能武器 `DataComponents#KINETIC_WEAPON` 影响实体的使用(例如,右键单击)行为。在右键单击时,如果物品具有该组件,则每刻调用 `KineticWeapon#damageEntities` 而不是 `Item#onUseTick`,仅在服务器上。动能武器也会调用 `LivingEntity#stabAttack` 来伤害其实体,类似于穿刺攻击。实际上,该组件本身与 `PiercingWeapon` 类似,只是多了几个字段来处理应用的动能伤害,并使其适用于所有活体实体而不仅仅是玩家。 要使刺击攻击发生,必须满足其中一个条件(下马、击退、伤害)并返回 true。攻击范围从 `DataComponents#ATTACK_RANGE` 组件获得。如果发生刺击攻击,则会在服务器上触发 `SPEAR_MOBS_TRIGGER` 条件。 ```java // 对于某个物品注册 new Item(new Item.Properties.component( DataComponents.KINETIC_WEAPON, new KineticWeapon( // 此实体在尝试接触(例如,伤害)另一个实体之前等待的刻数。 10, // 在尝试刺击范围内的任何实体之前等待的刻数。 20, // 检查此物品的攻击是否会使载具中的实体下马的条件。 // 如果 optional 不存在,则默认为 false。 Optional.of(new KineticWeapon.Condition( // 从此条件可能返回 true 的首次使用加延迟的最大刻数。 100, // 此条件成功所需的实体移动的最小速度。 // 速度计算为增量运动与视图向量的点积乘以 20。 // 原版矛对下马使用 7-14 的值,对击退使用 5.1。 9f, // 此条件成功所需的,相对于攻击实体的此实体的最小移动速度。 // 原版矛对伤害使用 4.6。 5f )), // 检查此物品的攻击是否会对实体造成击退的条件。 // 如果 optional 不存在,则默认为 false。 Optional.of(KineticWeapon.Condition.ofAttackerSpeed( // 最大刻数 100, // 实体移动速度 5.1f )), // 检查此物品的攻击是否会伤害实体的条件。 // 如果 optional 不存在,则默认为 false。 Optional.of(KineticWeapon.Condition.ofRelativeSpeed( // 最大刻数 100, // 相对移动速度 4.6f )), // 第三人称攻击动画期间物品的移动 // 原版矛使用 0.38。 0.38f, // 应用于实体伤害的乘数 // 伤害计算为此实体相对于其目标的相对移动速度。 4f, // 首次使用此物品时播放的声音。 // 如果 optional 为空,则不播放声音。 Optional.of(SoundEvents.LLAMA_SWAG), // 此物品击中实体时播放的声音。 // 如果 optional 为空,则不播放声音。 Optiona.of(SoundEvents.ITEM_BREAK) ) )); ``` - `net.minecraft.core.components` - `DataComponents` - `USE_EFFECTS` - 使用物品时应用于实体的效果。 - `MINIMUM_ATTACK_CHARGE` - 使用物品攻击的最短时间。 - `DAMAGE_TYPE` - 物品造成的 `DamageType` - `PIERCING_WEAPON` - 一种具有某些碰撞箱范围并向实体冲刺的武器。 - `KINETIC_WEAPON` - 一种需要一定前进动量的具有碰撞箱范围的武器。 - `SWING_ANIMATION` - 挥动物品时应用的动画。 - `ATTACK_RANGE` - 使用物品时设置自定义攻击范围,覆盖正常的实体交互范围。 - `net.minecraft.core.component.DataComponentType#ignoreSwapAnimation`、`$Builder#ignoreSwapAnimation` - 当为 true 时,交换动画不会影响数据组件的“使用”。 - `net.minecraft.core.component.predicates` - `AnyValue` - 一个谓词,检查获取器上是否存在该组件。 - `DataComponentPredicate` - `$Type` 现在是一个接口 - 其原始实现已被 `$TypeBase` 取代 - `$AnyValueType` - 一个使用 `AnyValue` 谓词的类型。 - `$ConcreteType` - 一个定义特定谓词的类型。 - `net.minecraft.network.protocol.game.ServerboundInteractPacket#isWithinRange` - 玩家的交互是否在有效范围内以执行。 - `net.minecraft.world.entity` - `LivingEntity` - `SWING_DURATION` -> `SwingAnimation#duration`,不是一对一 - `stabbedEntities` - 最近被动能武器攻击的实体数量。 - `entityAttackRange` - 此实体可以攻击的范围。 - `getActiveItem` - 当前使用的物品,或主手物品。 - `Mob` - `chargeSpeedModifier` - 冲刺时应用于移动速度的修改器。 - `canFireProjectileWeapon` -> `canUseNonMeleeWeapon`,现在接受 `ItemStack` 而不是 `ProjectileWeaponItem` - `getAttackBoundingBox` 现在接受一个水平膨胀偏移 - `net.minecraft.world.entity.ai.behavior` - `ChargeAttack` - 处理生物执行的冲刺攻击。 - `SpearApproach` - 当持有动能武器时接近敌人。 - `SpearAttack` - 使用动能武器攻击敌人。 - `SpearRetreat` - 使用动能武器后从攻击目标逃跑。 - `net.minecraft.world.entity.ai.goal.SpearUseGoal` - 处理生物使用矛。 - `net.minecraft.world.entity.ai.memory.MemoryModuleType` - `SPEAR_FLEEING_TIME` - 使用动能武器后实体已逃跑的刻数。 - `SPEAR_FLEEING_POSITION` - 使用动能武器后实体逃跑到的位置。 - `SPEAR_CHARGE_POSITION` - 使用动能武器时实体冲刺到的位置。 - `SPEAR_ENGAGE_TIME` - 使用动能武器时此实体与敌人交战的时间。 - `SPEAR_STATUS` - 使用动能武器时实体的状态。 - `net.minecraft.world.entity.player.Player` - `hasEnoughFoodToDoExhaustiveManoeuvres` - 返回玩家是否可以进行消耗体力的机动。 - `canInteractWithEntity` -> `isWithinEntityInteractionRange` - `isWithinAttackRange` - 被瞄准的边界框是否在玩家的范围内。 - `canInteractWithBlock` -> `isWithinBlockInteractionRange` - `CREATIVE_ENTITY_INTERACTION_RANGE_MODIFIER_VALUE` - 一个修饰符,将交互的最大范围增加给定的数量。 - `net.minecraft.world.item` - `Item#getDamageSource` -> `getItemDamageSource`,现已弃用 - `ItemStack` - `getSwingAnimation` - 返回物品的挥动动画。 - `getDamageSource` - 返回物品被击中时提供的伤害来源。 - `causeUseVibration` - 如果使用中的物品可以引起振动,则发送游戏事件。 - `SwingAnimationType` - 挥动物品时播放的动画类型。 - `net.minecraft.world.item.component` - `AttackRange` - 此物品的碰撞箱范围。 - `KineticWeapon` - 一种需要一定前进动量的武器。 - `PiercingWeapon` - 一种向实体冲刺的武器。 - `SwingAnimation` - 挥动物品时应用的动画。 - `UseEffects` - 使用物品时应用于实体的效果。 ## 环境属性的时间线 环境属性,顾名思义,为给定的维度(dimension)和/或生物群系(biome)(统称为“环境”)定义了一组属性或修改(“attributes”)。它们直接存储在生物群系或维度类型的 `attributes` 字段下,或作为可变时间线下 `tracks` 字段的一部分。每个属性可以代表从视觉设置到游戏行为的任何内容,在不同值之间进行插值。原版在 `EnvironmentAttributes` 中提供了它们可用的属性,而存储的属性则从 `Level#environmentAttributes` 获得。 ```json5 // 对于某个 DimensionType json // 在 `data/examplemod/dimension_type/example_dimension.json` { // 定义在维度内应用的属性 "attributes": { // 设置云高度 // 更技术地说,通过覆盖来修改值 "minecraft:visual/cloud_height": 90 }, // ... } // 对于某个 Biome json // 在 `data/examplemod/worldgen/biome/example_biome.json` { // 定义在生物群系内应用的属性 // 默认或修改维度中的属性 // 这些属性必须是位置性的 "attributes": { "minecraft:visual/cloud_height": { // 不设置值,而是应用一个修改器 "modifier": "add", // 将 60 加到 90,使该生物群系的云高度为 150 "argument": 60 } } // ... } // 对于某个 Timeline json // 在 `data/examplemod/timeline/example_timeline.json { // 此轨道在重复之前花费的刻数 "period_ticks": 24000, // 定义要基于定义的 // 关键帧进行插值的属性。 // 默认或修改生物群系或维度中的属性 "tracks": { "minecraft:visual/cloud_height": { // 定义属性特定值的关键帧 "keyframes": [ { // 表示关键帧的刻 "tick": 12000, // 修改值的参数 // 在这种情况下,将 1 加到 60 + 90,使云高度为 151 "value": 1 }, { // 表示关键帧的刻 "tick": 23999, // 修改值的参数 // 在这种情况下,将 0 加到 60 + 90,使云高度为 150 "value": 0 } ], // 不设置值,而是将修改器应用于参数 "modifier": "add", // 在刻之间进行插值时应用的采样函数 "ease": "linear" } } } ``` 当调用 `EnvironmentAttributeSystem#getValue` 时,属性值通过 `Level` 定义的层获得: 1. 从注册的属性中读取默认值(通过 `EnvironmentAttribute#defaultValue`)。 2. 应用来自维度的修改器,如果该属性不存在则不执行任何操作。 3. 应用来自生物群系的修改器,如果不存在则不执行任何操作。 4. 应用 `DimensionType` 中定义的所有活动时间线的修改器,如果不存在则不执行任何操作。时间线顺序不保证。 5. 如果维度可以有天气(天空光照、无天花板、且不是末地),则应用 `WeatherAttributes` 的修改器。 6. 如果在客户端(即 `ClientLevel`),则应用天空闪光修改器。 7. 将最终值清理到 `EnvironmentAttribute` 定义的范围内。 这是高度简化的,并引入了许多新概念,因此让我们通过创建我们自己的环境属性和时间线来进一步分解。 ### 自定义环境属性 环境属性通过 `$Builder` 创建,使用 `EnvironmentAttribute#builder`,接受其表示的类型值(例如,浮点数、整数、对象)。构建器只需要设置一个值:`defaultValue`。如果维度或生物群系未覆盖该属性,则使用此值。如果属性值应具有一组有效的状态,则可以通过 `valueRange` 设置 `AttributeRange`。`AttributeRange` 基本上是一个一元运算符,通过 `sanitize` 将输入转换为其“有效”状态。它还通过 `validate` 验证通过 JSON 传入的值是否处于“有效”状态。 从那里开始,还有三个方法负责确定用于计算值的逻辑。`$Builder#syncable` 将属性同步到客户端,这对于任何导致某种变化的属性(例如,视觉、音频或通用代码)是必需的。`notPositional` 意味着该属性不能应用于生物群系(仍可在维度或时间线中设置),否则会抛出异常。最后,`spatiallyInterpolated` 将尝试使用属性类型在不同的生物群系之间进行插值,以应用更无缝的过渡。原版仅处理客户端属性的空间插值。服务器上的任何内容都必须处理自己的 `SpatialAttributeInterpolator`。 最后,实际属性可以通过 `$Builder#build` 获得。该值必须注册到 `BuiltInRegistries#ENVIRONMENT_ATTRIBUTE`: ```java public static final EnvironmentAttribute EXAMPLE_ATTRIBUTE = Registry.register( BuiltInRegistries.ENVIRONMENT_ATTRIBUTE, Identifier.withNamespaceAndPath("examplemod", "example_attribute"), EnvironmentAttribute.builder( // 属性类型 // 必须与属性值的泛型匹配 AttributeTypes.BOOLEAN ) // 此属性应默认具有的值 .defaultValue(false) // 将此值同步到客户端 .syncable() .build() ); ``` ```json5 // 对于某个 DimensionType json // 在 `data/examplemod/dimension_type/example_dimension.json` { "attributes": { "examplemod:example_attribute": true }, // ... } // 对于某个 Biome json // 在 `data/examplemod/worldgen/biome/example_biome.json` { "attributes": { "examplemod:example_attribute": { "modifier": "xor", "argument": true } } // ... } // 对于某个 Timeline json // 在 `data/examplemod/timeline/example_timeline.json { "period_ticks": 24000, "tracks": { "examplemod:example_attribute": { "keyframes": [ { "tick": 12000, "value": false }, { "tick": 23999, "value": true } ], "modifier": "and", "ease": "linear" } } } ``` ### 自定义属性类型 每个环境属性都有一个关联的属性类型,静态注册到 `BuiltInRegistries#ATTRIBUTE_TYPE`。这不仅定义了如何序列化对象值,还包含可以应用于值的修改以及如何在空间和帧之间进行插值。实际上,包括 `syncable` 和 `spatiallyInterpolated` 在内的所有构建器设置都依赖于属性类型来确定执行该操作意味着什么。如果没有它,甚至无法从维度或生物群系 JSON 中读取属性,更不用说获取属性值的实际逻辑了。 因此,属性类型可以分为三个部分:序列化编解码器、修改器库和插值函数。 ```java // 我们将使用此示例对象来解释属性类型 public record ExampleObject(int value1, boolean value2) { // 默认值 public static final ExampleObject DEFAULT = new ExampleObject(0, false); } ``` #### 类型序列化 属性类型的序列化通过该类型的编解码器处理,包括到磁盘(生物群系和维度 JSON)和网络(`$Builder#syncable`): ```java // 用于序列化属性类型值的编解码器 public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( Codec.INT.fieldOf("value1").forGetter(ExampleObject::value1), Codec.BOOL.fieldOf("value2").forGetter(ExampleObject::value2) ).apply(instance, ExampleObject::new) ); ``` #### 修改器库 修改器库是一个 `AttributeModifier$OperationId` 到 `AttributeModifier` 的映射,确定可以对默认值执行哪些操作。如果映射不包含任何操作,则默认值不能更改。`AttributeType` 的所有静态构造函数都添加了 `OVERRIDE` 修改器,允许维度和/或生物群系设置值。这个映射应该被视为一个伪注册表(基本上是键到唯一值的映射),因为用于序列化的默认编解码器是通过 id 解析器为 `BiMap` 提供的。 一个 `AttributeModifier` 定义了两个泛型:第一个是环境属性值类型,第二个是用于应用操作的任意对象。修改器有两个方法:`apply`,接受值和参数以返回一个新值;以及 `argumentCodec`,用于正确序列化参数。对于任何操作,所有可能的修改都必须实现在单个 `AttributeModifier` 中: ```java // 仅处理对象一部分的修改器 public static final AttributeModifier ADD = new AttributeModifier<>() { @Override public ExampleObject apply(ExampleObject subject, Integer argument) { // 将操作应用于 subject return new ExampleObject(subject.value1() + argument, subject.value2()); } @Override public Codec argumentCodec(EnvironmentAttribute attribute) { // 构造用于反序列化参数的编解码器 return Codec.INT; } }; public static final AttributeModifier OR = new AttributeModifier<>() { @Override public ExampleObject apply(ExampleObject subject, Boolean argument) { // 将操作应用于 subject return new ExampleObject(subject.value1(), subject.value2() || argument); } @Override public Codec argumentCodec(EnvironmentAttribute attribute) { // 构造用于反序列化参数的编解码器 return Codec.BOOL; } }; // 一个处理所有可能对象组合的修改器 public static final AttributeModifier>> AND = new AttributeModifier<>() { @Override public ExampleObject apply(ExampleObject subject, Either> argument) { return argument.map( arg -> new ExampleObject(subject.value1() & arg.value1(), subject.value2() && arg.value2()), either -> either.map( arg -> new ExampleObject(subject.value1() & arg, subject.value2()), arg -> new ExampleObject(subject.value1(), subject.value2() && arg) ) ); } @Override public Codec>> argumentCodec(EnvironmentAttribute attribute) { // 构造用于反序列化参数的编解码器 // 我们可以为值类型使用属性编解码器 return Codec.either(attribute.valueCodec(), Codec.either(Codec.INT, Codec.BOOL)); } }; // 构造库 // 参数可以是任何值,只要它可以被序列化和处理 // 如果使用属性类型的静态构造函数之一,则会自动添加覆盖 // 处理程序以及映射的关联修改器编解码器 public static final Map> EXAMPLE_LIBRARY = Map.of( AttributeModifier.OperationId.ADD, ADD, AttributeModifier.OperationId.OR, OR, AttributeModifier.OperationId.AND, AND ); ``` #### 类型插值 为了支持插值,无论是对于客户端帧(由于 `$Builder#syncable`)、空间(`$Builder#spatiallyInterpolated`)、状态(天气)还是关键帧(时间线),都需要一个函数,在给定 0 和 1 之间的某个步长(时间或位置)时,如何合并两个值。这通过 `LerpFunction` 处理,其泛型是环境属性值类型。对于非插值值,这通常使用 `LerpFunction#ofStep`,它类似于两个值之间的简单阈值。更具体地说,空间插值将阈值设置为 0.5,而部分刻、关键帧和状态更改将仅考虑完整步长(意味着总是下一个值)。然而,这个函数可以根据您的选择定义: ```java // Step 表示 0 和 1 之间的插值 // Original 表示步长为 0 的值 // Next 表示步长为 1 的值 public static final LerpFunction EXAMPLE_SPATIAL_LERP = (step, original, next) -> { return new ExampleObject( Mth.lerp(step, original.value1(), next.value1()), step >= 0.5f ? next.value2() : original.value2() ); } public static final LerpFunction EXAMPLE_PARTIAL_LERP = (step, original, next) -> { return new ExampleObject( Mth.lerp(step, original.value1(), next.value1()), next.value2() ); } // 将始终返回第一个值 public static final LerpFunction EXAMPLE_KEYFRAME_LERP = LerpFunction.ofConstant(); // 在步长过去 0.1 后更改为下一个状态 public static final LerpFunction EXAMPLE_STATE_CHANGE_LERP = LerpFunction.ofStep(0.1f); ``` #### 整合在一起 有了这些部分,现在可以构造一个 `AttributeType`。这通常使用静态构造函数之一完成:`ofInterpolated` 用于定义其插值函数的值,或 `ofNotInterpolated` 用于可以在两个值之间直接切换的值。对于常见用例,除非您的值在玩家自然可见的内容(例如,雾或天空颜色的视觉)之间过渡,否则插值通常是不必要的。 如果您决定改用 `AttributeType` 实例构造函数,您还需要创建一个编解码器来序列化修改器映射。请参阅 `AttributeType#createModifierCodec` 了解如何操作。 ```java // 属性类型必须静态注册才能被正确处理 public static final AttributeType EXAMPLE_ATTRIBUTE_TYPE = Registry.register( BuiltInRegistries.ATTRIBUTE_TYPE, Identifier.withNamespaceAndPath("examplemod", "example_attribute_type"), new AttributeType<>( // 值的编解码器 ExampleObject.CODEC, // 可以修改的操作映射 // `OVERRIDE` 会自动添加用于序列化 EXAMPLE_LIBRARY, // 用于序列化修改器库的编解码器 Util.make(() -> { ImmutableBiMap> map = ImmutableBiMap.builder() .put(AttributeModifier.OperationId.OVERRIDE, AttributeModifier.override()) .putAll(EXAMPLE_LIBRARY) .buildOrThrow(); return ExtraCodecs.idResolverCodec(AttributeModifier.OperationId.CODEC, map::get, map.inverse()::get); }), // 在时间线中两个关键帧之间插值的函数 EXAMPLE_KEYFRAME_LERP, // 在两个状态之间插值的函数(仅用于天气映射中的属性) EXAMPLE_STATE_CHANGE_LERP, // 在两个空间坐标之间插值的函数 EXAMPLE_SPATIAL_LERP, // 在客户端帧之间插值的函数 EXAMPLE_PARTIAL_LERP ) ); ``` 从那里,我们可以创建一个使用该类型的 `EnvironmentAttribute`: ```java public static final EnvironmentAttribute EXAMPLE_OBJECT_ATTRIBUTE = Registry.register( BuiltInRegistries.ENVIRONMENT_ATTRIBUTE, Identifier.withNamespaceAndPath("examplemod", "example_object_attribute"), EnvironmentAttribute.builder( EXAMPLE_ATTRIBUTE_TYPE ) .defaultValue(ExampleObject.DEFAULT) // 由于编解码器和部分刻插值而可能 .syncable() // 由于空间插值而可能 .spatiallyInterpolated() .build() ); ``` ```json5 // 对于某个 DimensionType json // 在 `data/examplemod/dimension_type/example_dimension.json` { "attributes": { "examplemod:example_object_attribute": { "value1": 10, "value2": true } }, // ... } // 对于某个 Biome json // 在 `data/examplemod/worldgen/biome/example_biome.json` { "attributes": { "examplemod:example_object_attribute": { // 必须使用库中定义的参数之一 // 在这种情况下是 'add'、'or' 或 'and' "modifier": "and", // 这可以是布尔值、整数或对象 // 因为序列化器是这样定义的 "argument": false } } // ... } // 对于某个 Timeline json // 在 `data/examplemod/timeline/example_timeline.json { "period_ticks": 24000, "tracks": { "examplemod:example_object_attribute": { "keyframes": [ { "tick": 12000, // 这可以是布尔值、整数或对象 // 因为序列化器是这样定义的 "value": 1 }, { "tick": 23999, // 这可以是布尔值、整数或对象 // 因为序列化器是这样定义的 "value": { "value1": 0, "value2": false } } ], // 必须使用库中定义的参数之一 // 在这种情况下是 'add'、'or' 或 'and' "modifier": "and", "ease": "linear" } } } ``` ### 时间线 `Timeline` 是一种基于当前游戏时间修改属性的方法。更具体地说,它们定义了一些关键帧,值在关键帧之间进行插值,首先使用 `EasingType` 函数确定步长,其次使用 `AttributeType#keyframeLerp` 获取值。这不仅是大脑中 `Schedule` 的替代品,也是与昼夜循环相关的属性(例如,天空颜色、史莱姆生成几率等)的替代品。它们作为生物群系修改器之后的一层,用于位置性和非位置性属性。 时间线基于 `DimensionType#timelines` 标签激活,这些标签以 `in_` 为前缀(例如,`minecraft:in_overworld` 是主世界的时间线标签)。所有维度标签都包括 `minecraft:universal` 标签,这意味着所有标记的时间线将在所有维度内运行(前提是它们添加了 universal 标签)。 原版时间线如下: - `minecraft:day`: 昼夜循环 - `minecraft:moon`: 月相和生成几率 - `minecraft:villager_schedule`: 村民执行什么 `Activity` - `minecraft:early_game`: 在最初几天阻止掠夺者巡逻队生成 关联的标签如下: - `minecraft:universal` - `minecraft:villager_schedule` - `minecraft:in_overworld` - 主世界维度 - `#minecraft:universal` - `minecraft:day` - `minecraft:moon` - `minecraft:early_game` - `minecraft:in_nether` - 下界维度 - `#minecraft:universal` - `minecraft:in_end` - 末地维度 - `#minecraft:universal` #### 关键帧 每个 `Timeline` 由关键帧组成,负责确定在给定刻时修改器的参数应该是什么。然后,这些关键帧被编译成一个称为 `KeyframeTrack` 的列表,在构造属性层时烘焙成一个 `KeyframeTrackSampler`。每两个相邻的关键帧(包括第一个和最后一个)被认为是一个 `KeyframeTrackSampler$Segment`。这就是用于在给定刻采样属性的内容。 假设我们有以下(关键帧,值)段 (100, 0) -> (200, 1),并且我们当前在 150 刻。我们如何选择使用什么参数?这通过两个操作执行。首先,我们计算步长:介于 `0` 和 `1` 之间的值,决定与值进行多少插值。步长首先线性计算:(current_tick - start_segment_tick) / (end_segment_tick - start_segment_tick)。然后,将步长传递给所需的 `EasingType`,这是一个接受 0-1 值并返回 0-1 值的函数,例如 `in_out_bounce` 或 `out_back`。您也可以像这样创建自己的 `EasingType`: ```java // `EasingType#registerSimple` 必须设为公开 EasyingType.registerSimple( // 函数的名称 "examplemod:ease", // 应用于值的函数 // 对于平滑过渡,函数应将 0 -> 0 和 1 -> 1 original -> 0.5f * (float) Mth.sin(Math.PI * (3 * original - 0.5)) + 0.5f ); ``` 然后,它将步长与两个参数一起传递给 `AttributeType#keyframeLerp` 函数,以获得要应用的插值参数。 #### 属性轨道 通过确定参数的关键帧,我们通过一个 `AttributeTrack` 将参数应用于属性,在构造属性层时烘焙成一个 `AttributeTrackSampler`。一个 `AttributeTrack` 包含获取参数的 `KeyframeTrack`,以及将参数应用于值的 `ArgumentModifier`。请注意,对于给定的轨道只能有一个修改器。 这些 `AttributeTrack` 然后存储在一个属性到轨道的映射中,这定义了我们的 `Timeline`。时间线还包含一个可选的整数,表示轨道的周期。这里的“period”充当时间线中所有轨道的一次完整运行。超出周期的值取模。大多数时间线使用 `24000` 作为周期,因为这代表 Minecraft 一天中的刻数。 #### 自定义时间线 自定义 `Timeline` 被添加到 `timeline` 数据包注册表: ```json5 // 对于某个 Timeline json // 在 `data/examplemod/timeline/example_timeline.json { // 每 3000 刻运行一次(一天的 1/8) "period_ticks": 3000, "tracks": { // 要修改的属性 "examplemod:example_object_attribute": { // 确定参数之间步长的缓动函数 "ease": "examplemod:ease", // 定义在设置刻的参数的关键帧列表 // 然后使用缓动函数和关键帧插值对参数进行插值 "keyframes": [ { // 此参数为给定值的刻 "tick": 1500, // 将 10 加到属性 "value": 10 }, // 在中间,使用缓动函数在 10 和 0 之间逐步下降 { "tick": 2999, // 将 0 加到属性 "value": 0 } // 在中间,使用缓动函数在 0 和 10 之间逐步上升 ], // 将参数应用于值时要使用的修改器 "modifier": "add" } } } ``` - `net.minecraft.client` - `Camera#attributeProbe` - 获取客户端环境属性探测器的值和插值。 - `Minecraft` - `getSituationalMusic` 现在返回 `Music` 而不是 `MusicInfo` - `getMusicVolume` - 获取背景音乐的音量,如果打开的屏幕有背景音乐则获取正常音量。 - `net.minecraft.client.multiplayer.ClientLevel` - `effects` 已移除 - `getSkyDarken` -> `EnvironmentAttributes#SKY_LIGHT_COLOR`、`SKY_LIGHT_FACTOR`;不是一对一 - `getSkyColor` -> `EnvironmentAttributes#SKY_COLOR`,不是一对一 - `getCloudColor` -> `EnvironmentAttributes#CLOUD_COLOR`,不是一对一 - `getStarBrightness` -> `EnvironmentAttributes#STAR_BRIGHTNESS`,不是一对一 - `getSkyFlashTime` 现在是私有的 - `net.minecraft.client.renderer` - `DimensionSpecialEffects` 类已移除,完全被 `EnvironmentAttribute` 取代 - `SkyRenderer` - `renderSkyDisc` 现在接受一个 ARGB `int` 而不是三个 RGB `float` - `renderSunMoonAndStars` 现在接受两个额外的 `float` 用于月亮和星星的旋转 - `net.minecraft.client.renderer.state.SkyRenderState` - `skyType` -> `skybox`,不是一对一 - `isSunriseOrSunset`、`timeOfDay` 已移除 - `moonAngle`、`starAngle` - 月亮和星星的角度。 - `net.minecraft.client.resources.sounds.BiomeAmbientSoundsHandler` 不再接受 `BiomeManager` - `net.minecraft.client.sounds` - `MusicInfo` -> `Minecraft#getSituationalMusic`、`getMusicVolume`;不是一对一 - `MusicManager#startPlaying` 现在接受 `Music` 而不是 `MusicInfo` - `net.minecraft.core.registries` - `BuiltInRegistries`、`Registries#ENVIRONMENT_ATTRIBUTE` - 环境属性的注册表。 - `BuiltInRegistries`、`Registries#ATTRIBUTE_TYPE` - 属性类型的注册表。 - `BuiltInRegistires`、`Registries#SCHEDULE` 已移除 - `Registries#TIMELINE` - 时间线的注册表键。 - `net.minecraft.data.tags.TimelineTagsProvider` - 时间线的标签提供者。 - `net.minecraft.server.level.ServerLevel#getMoonBrightness` - 返回月亮的亮度。 - `net.minecraft.sounds.Music#event` -> `sound` - `net.minecraft.tags.TimelineTags` - 时间线的标签。 - `net.minecraft.util` - `BinaryAnimator$EasingFunction` -> `EasingType` - `CubicSampler` -> `GaussianSampler`、`SpatialAttributeInterpolator`;不是一对一 - `KeyframeTrack` - 一个关键帧轨道以及它们之间执行的缓动。 - `KeyframeTrackSampler` - 一个基于周期重播的关键帧轨道,使用提供的函数在值之间进行插值。 - `net.minecraft.world.attribute` - `AmbientSounds` - 在环境中环境播放的声音。 - `AttributeRange` - 一个接口,用于验证输入并将相应值清理到适当的边界。 - `AttributeType` - 属性可以执行的操作和修改的类型定义。 - `AttributeTypes` - 所有原版属性类型的注册表。 - `BackgroundMusic` - 在环境中播放的背景音乐。 - `BedRule` - 环境中床的功能规则。 - `EnvironmentAttribute` - 环境中某个属性的定义。 - `EnvironmentAttributeLayer` - 一个修改值的层。 - `EnvironmentAttributeMap` - 属性定义到其参数和修改器的映射。 - `EnvironmentAttributeProbe` - 用于获取和插值值的属性处理程序。仅由相机使用。 - `EnvironmentAttributeReader` - 一个可以通过维度或位置查找环境属性的读取器。 - `EnvironmentAttributes` - 所有原版环境属性的注册表。 - `EnvironmentAttributeSystem` - 一个获取和空间插值环境属性的读取器实现。 - `LerpFunction` - 一个函数式接口,接受 0-1 之间的某个值以及起始和结束值以在之间进行插值。 - `WeatherAttributes` - 用于应用天气层的属性映射。 - `net.minecraft.world.attribute.holder` - `AttributeModifier` - 一个修改器,接受属性值以及某个参数(通常是相同类型的值)以产生修改后的值。 - `BooleanModifier` - 带有布尔参数的布尔值修改器。 - `ColorModifier` - 带有某个参数(通常是整数)的 ARGB 整数修改器。 - `FloatModifier` - 带有某个参数(通常是浮点数或带有 alpha 插值器的浮点数)的浮点数修改器。 - `FloatWithAlpha` - 一个包含某个值和通常用于混合的 alpha 的记录。 - `net.minecraft.world.entity.ai.Brain` - `getSchedule` 已移除 - `setSchedule` 现在接受 `EnvrionmentAttribute` 而不是 `Schedule` - `updateActivityFromSchedule` 现在接受 `EnvironmentAttributeSystem` 和位置而不是白天时间 - `net.minecraft.world.entity.animal.bee.Bee#isNightOrRaining` 被 `EnvironmentAttributes#BEES_STAY_IN_HIVE` 取代 - `net.minecraft.world.entity.player.Player$BedSleepingProblem` 现在是一个记录 - `NOT_POSSIBLE_HERE` -> `BedRule#EXPLODES` - `NOT_POSSIBLE_NOW` -> `BedRule#CAN_SLEEP_WHEN_DARK` - `net.minecraft.world.entity.schedule` - `Keyframe` -> `.minecraft.util.Keyframe`,不是一对一 - `Schedule` 已移除,其逻辑被 `Timeline`、`Timelines` 取代 - `ScheduleBuilder` 已移除,其逻辑被 `Timeline$Builder` 取代 - `Timeline` -> `.world.timeline.Timeline`,不是一对一 - `net.minecraft.world.entity.variant.SpawnContext` 现在接受 `EnvironmentAttributeReader` - `net.minecraft.world.level` - `Level` - `isMoonVisible` 被 `EnvironmentAttributes#MOON_ANGLE` 取代 - `getSunAngle` 被 `EnvironmentAttributes#SUN_ANGLE` 取代 - `canHaveWeather` 现在是 `public` - `LevelAccessor` 现在实现 `LevelReader` 而不是 `LevelTimeAccess` - `LevelReader#environmentAttributes` - 返回管理器,用于获取维度及其关联生物群系内的环境属性。 - `LevelTimeAccess` 接口已移除 - `MoonPhase` - `CODEC` - 月相的编解码器。 - `PHASE_LENGTH` - 月相存在的刻数。 - `startTick` - 特定相位的开始刻。 - `net.minecraft.world.level.biome` - `AmbientAdditionsSettings` -> `.world.attribute.AmbientAdditionsSettings` - `AmbientMoodSettings` -> `.world.attribute.AmbientMoodSettings` - `AmbientParticleSettings` -> `.world.attribute.AmbientParticle` - `Biome` 现在接受 `EnvironmentAttributeMap` - `getSkyColor` -> `EnvironmentAttributes#SKY_COLOR` - `getFogColor` -> `EnvironmentAttributes#FOG_COLOR` - `getAttributes` - 获取此生物群系的属性。 - `getWaterFogColor` -> `EnvironmentAttributes#WATER_FOG_COLOR` - `getAmbientParticle` -> `EnvironmentAttributes#AMBIENT_PARTICLES` - `getAmbientLoop` -> `AmbientSounds#loop` 环境属性 - `getAmbientMood` -> `AmbientSounds#mood` 环境属性 - `getAmbientAdditions` -> `AmbientSounds#additions` 环境属性 - `getBackgroundMusic` -> `EnvironmentAttributes#BACKGROUND_MUSIC` - `getBackgroundMusicVolume` -> `EnvironmentAttributes#MUSIC_VOLUME` - `$Builder` - `putAttributes` - 从另一个映射放入所有属性。 - `setAttribute` - 设置一个环境属性。 - `modifyAttribute` - 修改生物群系的属性源。 - `BiomeSpecialEffects` 现在是一个记录 - `getFogColor` -> `EnvironmentAttributes#FOG_COLOR` - `getWaterFogColor` -> `EnvironmentAttributes#WATER_FOG_COLOR` - `getSkyColor` -> `EnvironmentAttributes#SKY_COLOR` - `getAmbientParticleSettings` -> `EnvironmentAttributes#AMBIENT_PARTICLES` - `getAmbientLoopSoundEvent` -> `AmbientSounds#loop` 环境属性 - `getAmbientMoodSettings` -> `AmbientSounds#mood` 环境属性 - `getAmbientAdditionsSettings` -> `AmbientSounds#additions` 环境属性 - `getBackgroundMusic` -> `EnvironmentAttributes#BACKGROUND_MUSIC` - `getBackgroundMusicVolume` -> `EnvironmentAttributes#MUSIC_VOLUME` - `net.minecraft.world.level.block` - `BedBlock#canSetSpawn` -> `BedRule#canSetSpawn` 环境属性 - `CreakingHeartBlock#isNaturalNight` 被 `EnvironmentAttributes#CREAKING_ACTIVE` 取代 - `RespawnAnchorBlock#canSetSpawn` 现在接受 `ServerLevel` 和 `BlockPos` - `net.minecraft.world.level.dimension` - `BuiltinDimensionTypes#*_EFFECTS` 已移除 - `DimensionDefaults#OVERWORLD_CLOUD_HEIGHT` 现在是一个 `float` - `DimensionType` - `fixedTime` -> `hasFixedTime`,现在是 `boolean` 而不是 `OptionalLong` - `natural`、`effectsLocation` 已移除 - `skybox` - 在维度内显示的天空盒。 - `cardinalLightType` - 贯穿维度的光线类型。 - `timelines` - 一组修改此维度环境属性的时间线。 - `ultraWarm` -> `EnvironmentAttributes#WATER_EVAPORATES`、`FAST_LAVA`、`DEFAULT_DRIPSTONE_PARTICLE` - `bedWorks` -> `EnvironmentAttributes#BED_RULE` - `respawnAnchorWorks` -> `EnvironmentAttributes#RESPAWN_ANCHOR_WORKS` - `cloudHeight` -> `EnvironmentAttributes#CLOUD_HEIGHT` - `attribute` - 获取此维度的属性。 - `piglinSafe`、`$MonsterSettings#piglinSafe` -> `EnvironmentAttributes#PIGLINS_ZOMBIFY` - `hasRaids`、`$MonsterSettings#hasRaids` -> `EnvironmentAttributes#CAN_START_RAID` - `timeOfDay` 已移除 - `moonPhase` 被 `EnvironmentAttributes#MOON_PHASE` 取代 - `hasEndFlashes` - 返回天空盒是否是末地。 - `$CardinalLightType` - 贯穿维度的光线。 - `$Skybox` - 维度的天空盒。 - `net.minecraft.world.level.material.FogType#DIMENSION_OR_BOSS` 已移除 - `net.minecraft.world.timeline` - `AttributeTrack` - 一个轨道,应用属性修改器,其参数从给定的关键帧轨道采样。 - `AttributeTrackSampler` - 一个烘焙的属性轨道。 - `Timeline` - 一个属性到轨道的映射,基于时间(以刻为单位)模周期应用。 - `Timelines` - 所有原版时间线。 ## 游戏规则洗牌 游戏规则系统已在一定程度上被改造,允许将其键存储为适当的注册表对象,同时仍将其值限制为整数或布尔值。大多数类基本上只是其他类的组合。 ### 现有游戏规则 现有的游戏规则仍然在 `GameRules` 类中,只是移到了不同的位置。它们的字段已被重命名,并似乎遵循一些基本规则: 1. 规则不再有 `RULE_` 前缀 1. 规则现在使用下划线分隔单词 1. `DO` 前缀已从规则名称中移除(例如,`RULE_DOENTITYDROPS` -> `ENTITY_DROPS`) 1. `SPAWNING` 后缀已替换为 `SPAWN_` 前缀(例如,`RULE_DOMOBSPAWNING` -> `SPAWN_MOBS`) 1. `DISABLE` 前缀已移除,意味着它们的值被反转(例如,`RULE_DISABLERAIDS` -> `RAIDS`) 虽然有一些边缘情况,但在之前的游戏规则名称中搜索特定单词很可能会引导您找到新名称(例如,在 `RULE_ANNOUNCEADVANCEMENTS` 中搜索 `ADVANCEMENT` 会找到 `SHOW_ADVANCEMENT_MESSAGES`)。 要实际从游戏规则中获取值,您将使用 `GameRules#get` 而不是之前的 `getBoolean` 和 `getInteger`。类型从注册的 `GameRule` 上的泛型获得。 ```java // 使用 ServerLevel level boolean fallDamage = level.getGameRules().get(GameRules.FALL_DAMAGE); ``` 此外,设置游戏规则现在简化为调用 `GameRules#set`——接受 `GameRule`、值和当前服务器,如果更改通过 `MinecraftServer#onGameRuleChanged` 传播,通常应该这样做。 ```java // 使用 ServerLevel level level.getGameRules().set(GameRules.FALL_DAMAGE, false, level.getServer()); ``` ### 创建游戏规则 游戏规则通过 `GameRule` 类创建,它基本上是一个类型定义,说明游戏规则如何根据其调用者运行。其泛型表示所持有的值的类型。唯一将此与通用类型区分开的硬编码概念是,实际参数可以被限制在特定范围内,并且它们存储默认值。否则,这些字段与其在 `GameRules$Type` 和 `GameRules$Key` 中的前身基本相同。 然后,一旦创建,`GameRule` 必须静态注册到 `BuiltInRegistries#GAME_RULE` ```java public static final GameRule EXAMPLE_RULE = Registry.register( BuiltInRegistries.GAME_RULE Identifier.withNamespaceAndPath("examplemod", "example_rule"), new GameRule( // 最能代表游戏规则的类别。 // 这仅在首次构造世界时 // 由编辑游戏规则屏幕使用。 // 可以通过调用 `GameRuleCategory#register` 或仅使用其构造函数 // 创建自定义类别,因为排序顺序未使用 GameRuleCategory.register( Identifier.withNamespaceAndPath("examplemod", "example_category") ), // 游戏规则的类型,表示泛型的 // JSON 模式版本。 // 这仅由管理系统用于 // 检查非类型化规则。 GameRuleType.INT, // 用于在命令中序列化值的参数类型。 // 这可以根据构造函数进行范围限制。 IntegerArgumentType.integer(0, 5), // 一个调用者,通常在访问过程中运行 // 对于每个游戏规则。 // 此调用者仅由编辑游戏规则屏幕使用 // 用于添加修改值的正确组件。 // 不应在此处使用 `GameRuleTypeVisitor#visit` // 因为访问者已经调用了该函数。 GameRuleTypeVisitor::visitInteger, // 用于将游戏规则序列化到磁盘 // 或用于管理服务的编解码器。 // 这可以根据构造函数进行范围限制。 Codec.intRange(0, 5), // 一个将设置值映射到整数结果的函数 // 在通过命令设置或查询游戏规则时使用。 // 这是唯一 `0` 的结果不意味着命令失败的情况。 gameRuleValue -> gameRuleValue, // 此规则的默认值。 3, // 此规则在游戏中启用所需的功能标志集。 // 空的标志集意味着它应始终启用。 FeatureFlagSet.of() ) ); ``` - `net.minecraft.client.gui.screens.worldselection` - `EditGameRulesScreen` - `$BooleanRuleEntry` 现在接受 `GameRule` 而不是 `GameRules$BooleanValue` - `$EntryFactory` 不再限制其泛型 - `$IntegerRuleEntry` 现在接受 `GameRule` 而不是 `GameRules$IntegerValue` - `InitialWorldCreationOptions#disabledGameRules` 现在是一个 `GameRuleMap` - `net.minecraft.core.registries.BuiltInRegistries#GAME_RULE`、`Registries#GAME_RULE` - 游戏规则注册表。 - `net.minecraft.gametest.framework.TestEnvironmentDefinition` - `$SetGameRules` 现在接受 `GameRulesMap` 而不是 `$Entry` - `entry`、`$Entry` 已移除 - `net.minecraft.server.MinecraftServer#onGameRuleChanged` 现在接受 `GameRule` 和值,而不是字符串键和 `$Value` 包装器 - `net.minecraft.server.jsonrpc.api.Schema` - `RULE_TYPE_SCHEMA` 现在是 `GameRuleType` 而不是 `GameRulesService$RuleType` - `TYPED_GAME_RULE_SCHEMA` 现在是 `GameRulesService$GameRuleUpdate` 而不是 `GameRulesService$TypedRule` - `UNTYPED_GAME_RULE_SCHEMA` 现在是 `GameRulesService$GameRuleUpdate` 而不是 `GameRulesService$UntypedRule` - `net.minecraft.server.jsonrpc.internalapi` - `GameRules` 接口已移除 - `MinecraftGameRuleService#getRule` -> `getRuleValue` - `net.minecraft.server.jsonrpc.methods.GameRulesService` - `$RuleType` 已移除 - `$TypedRule`、`$UntypedRule` -> `$GameRuleUpdate`,不是一对一 - `net.minecraft.server.notifications.NotificationService#onGameRuleChanged` 现在接受 `GameRule` 和值,而不是字符串键和 `$Value` 包装器 - `net.minecraft.world.level.GameRules` - 静态规则键现在位于 `.gamerules.GameRules` 中,没有 `RULE_` 前缀,单词之间使用下划线 - `DO` 已从名称中移除(例如,`RULE_DOENTITYDROPS` -> `ENTITY_DROPS`) - `SPAWNING` 名称现在以 `SPAWN_` 开头(例如,`RULE_DOMOBSPAWNING` -> `SPAWN_MOBS`) - 将键映射到其关联值的映射行为现在由 `GameRuleMap` 处理 - `getBoolean`、`getInteger` -> `get` - `$Key`、`$Type` -> `GameRule`,不是一对一 - `GameRule` 实现 `FeatureElement` - `$Category` -> `GameRuleCategory`,不是一对一 - `$Value`、`$BooleanValue`、`$IntegerValue` 已移除,被直接包装的对象取代 - `$GameRuleTypeVisitor` -> `GameRuleTypeVisitor` ## 小幅迁移 以下是有用或有趣的增加、变更和移除的列表,它们不值得在入门文档中拥有自己的章节。 ### 使用注解 Mojang 最近为一些整数值和标志添加了注解,标记其预期用途。这不会以任何方式影响模组制作者,因为它似乎是一种对传递的值执行静态分析的方法,可能用于某种验证。 - `com.mojang.blaze3d.buffers.GpuBuffer$Usage` - 一个注解,标记给定的整数是否定义了特定缓冲区的用法标志。 - `com.mojang.blaze3d.platform.InputConstants$Value` - 一个注解,标记给定的整数是否定义了设备的输入。 - `com.mojang.blaze3d.buffers.GpuTexture$Usage` - 一个注解,标记给定的整数是否定义了特定纹理的用法标志。 - `net.minecraft.client.input` - `InputWithModifiers$Modifiers` - 一个注解,标记给定的整数是否定义了输入的修饰符。 - `KeyEvent$Action` - 一个注解,标记给定的整数是否定义了输入正在执行的操作(即,按下、释放、重复)。 - `MouseButtonInfo` - `$Action` - 一个注解,标记给定的整数是否定义了鼠标正在执行的操作(即,按下、释放、重复)。 - `$MouseButton` - 一个注解,标记给定的整数是否定义了鼠标的输入。 - `net.minecraft.server.level.TicketType$Flags` - 一个注解,标记给定的整数是否定义了加载票类型的标志。 - `net.minecraft.world.level.block.Block$UpdateFlags` - 一个注解,标记给定的整数是否定义了方块更新的标志。 ### 文本收集器 `ActiveTextCollector` 是一种提交字符串和组件进行渲染的方法,旨在提供对齐的通用实用程序,特别是对于超出屏幕的文本。虽然这不一定取代 `GuiGraphics#drawString`,但一些小部件需要使用 `ActiveTextCollector`,例如 `AbstractStringWidget#renderLines`。 可以通过调用 `GuiRenderer#textRenderer*` 方法之一来创建 `ActiveTextCollector`。它们接受一个 `$HoveredTextEffects`,它处理如何渲染组件的悬停和点击事件,以及一个用于任何额外处理的 `Style` 消费者回调。它还存储一组默认参数,这些参数基本上代表当前的姿势不透明度和屏幕矩形。 有两种方法可以提交一段文本进行渲染:`accept` 用于标准字符串,以及 `acceptScrolling*` 用于超出矩形的屏幕,以大约每秒一个单位的速度在屏幕上来回滚动(请参阅辅助功能设置中的示例)。`accept` 最多接受五个参数:X 位置的对齐方式(`TextAlignment#LEFT` 像正常一样,`CENTER` 文本的中心,`RIGHT` 文本的末尾)、对齐的 X 位置、Y 位置、要覆盖的参数以及文本。`acceptScrolling` 最多接受七个参数:文本、居中对齐的起始 X 位置、最左边的 X 位置、最右边的 X 位置、最顶部的 Y 位置、最底部的 Y 位置以及要覆盖的参数。 ```java // 在某个带有 GuiGraphics graphics 的方法中 ActiveTextCollector collector = graphics.textRenderer( // 渲染悬停和点击事件 HoveredTextEffects.TOOLTIP_AND_CURSOR; ); collector.accept( // 将文本对齐到中心 TextAlignment.CENTER, // 起始 X(在这种情况下是中心位置) 20, // 起始 Y 0, // 要使用的参数 collector.defaultParameters(), // 要显示的文本 Component.literal("世界你好!") ); ``` - `net.minecraft.client.gui` - `ActiveTextCollector` - 一个用于渲染具有某些参数和对齐方式的文本的辅助工具。 - `GuiGraphics` 现在接受鼠标 XY - `textRenderer*` - 用于构造在适当位置提交文本的辅助工具的方法。 - `$HoveredTextEffects` - 一个枚举,定义在使用文本收集器时应用的文本效果。 - `net.minecraft.client.gui.components` - `AbstractButton` 现在扩展 `AbstractWidget$WithInactiveMessage` 而不是 `AbstractWidget` - `renderWidget` 现在是 final - 请改用 `renderContents` 来提交元素 - 应在 `renderContents` 中调用 `renderDefaultSprite` 以 blit 默认精灵 - `renderString` -> `renderDefaultLabel`,不是一对一 - `AbstractSliderButton` 现在扩展 `AbstractWidget$WithInactiveMessage` 而不是 `AbstractWidget` - `AbstractStringWidget` - `visitLines` - 处理将文本元素提交到屏幕。 - `setColor`、`getColor` 已移除 - 请改用 `visitLines` 中的 `ActiveTextCollector` - `setComponentClickHandler` - 设置当点击具有提供样式的组件时的处理程序。 - `AbstractWidget` - `renderScrollingString` -> `renderScrollingStringOverContents`,不是一对一 - `getAlpha` - 获取小部件的 alpha 值。 - `$WithInactiveMessage` - 一个小部件,可以在不活动时更改显示的消息。 - `Button` 现在是抽象的 - `$Plain` 复制了以前的行为 - `ChatComponent` - `MESSAGE_BOTTOM_TO_MESSAGE_TOP` - 聊天组件的高度。 - `render` 现在接受 `Font` 和一个 `boolean`,表示是否在插入时更改光标 - `captureClickableText` - 捕获要提交的可点击文本。 - `handleChatQueueClicked` 被 `QUEUE_EXPAND_ID` 取代,不是一对一 - `getClickedComponentStyleAt` -> `$ChatGraphicsAccess#handleMessage`,不是一对一 - `getMessageTagAt` -> `$ChatGraphicsAccess#handleTag`、`handleTagIcon`;不是一对一 - `getWidth`、`getHeight`、`getScale` 现在是私有的 - `$AlphaCalculator` - 计算给定聊天行的 alpha 值。 - `$ChatGraphicsAccess` - 一个用于处理聊天输入提交的接口。 - `$LineConsumer` 不再接受前三个 `int` - `FittingMultilineTextWidget#setColor` 已移除 - 请改用 `visitLines` 中的 `ActiveTextCollector` - `MultiLineLabel` - `render`、`getStyle` -> `visitLines`,不是一对一 - `$Align` -> `TextAlignment` - `MultiLineTextWidget#setColor`、`configureStyleHandling` 已移除 - 请改用 `visitLines` 中的 `ActiveTextCollector` - `SplashRenderer` 现在接受 `Component` 而不是 `String` - `SpriteIconButton#renderSprite` - 提交精灵图标。 - `StringWidget#setColor` 已移除 - 请改用 `visitLines` 中的 `ActiveTextCollector` - `TabButton` 现在扩展 `AbstractWidget$WithInactiveMessage` 而不是 `AbstractWidget` - `renderString` -> `renderLabel`,现在是私有的,不是一对一 - `net.minecraft.client.gui.screens.inventory.BookViewScreen#getClickedComponentStyleAt` -> `visitText`,现在是私有的,不是一对一 ### 共享文本区域调试器 添加了一个新的调试器,用于绘制每个字形的边界框,包括空字形。颜色在每个字形之间略有偏移以便于区分,并且根据是否存在点击或悬停事件的某种组合而完全改变。 - `net.minecraft.SharedConstants#DEBUG_ACTIVE_TEXT_AREAS` - 用于调试器绘制每个字形的边界和效果的标志。 - `net.minecraft.client.gui.Font` - `prepareText` 现在有一个重载,表示是否在空区域渲染某些内容 - `$GlyphVisitor` - `acceptGlyph` 现在接受 `TextRenderable$Styled` 而不是 `TextRenderable` - `acceptEmptyArea` - 接受一个空区域以绘制到屏幕。 - `$PreparedTextBuilder` 现在接受是否包括空区域以进行渲染 - `net.minecraft.client.gui.font` - `ActiveArea` - 定义要绘制区域的边界和样式。 - `EmptyArea` - 一个内部没有任何内容的区域。 - `PlainTextRenderable` 现在实现 `TextRenderable$Styled` 而不是 `TextRenderable` - `width`、`height`、`ascent` - 对象的边界。 - `TextRenderable$Styled` - 一个为其边界定义某个活动区域的文本可渲染对象。 - `net.minecraft.client.gui.font.glyphs.BakedGlyph#createGlyph` 现在返回 `TextRenderable$Styled` ### JSpecify 注解 Mojang 已从使用他们自己的注解混合,转向在需要时使用 JSpecify 提供的注解。因此,不再默认所有字段、方法和参数都被标记为非空,而是由 `NullMarked` 取代,它认为类型用法是非空的,除非显式注解为 `Nullable`,除了一些特殊情况。 - `com.mojang.blaze3d.FieldsAreNonnullByDefault`、`MethodsReturnNonnullByDefault` 已移除 - `com.mojang.math.FieldsAreNonnullByDefault`、`MethodsReturnNonnullByDefault` 已移除 - `net.minecraft.FieldsAreNonnullByDefault`、`MethodsReturnNonnullByDefault` 已移除 ### 槽位来源 槽位来源是对之前在潜影盒中的内容掉落系统的扩展,允许任何战利品表从某些容器槽位中提取其条目。这可以在任何启用 `LootContext` 的位置使用,尽管目前它仅作为战利品池条目实现。 在原版中,槽位来源的工作方式是让某个 `LootContextArg`(指向某个战利品上下文参数值)返回一个实现 `SlotProvider` 的对象。目前,这指的是任何 `Container` 或 `Entity` 实现。然后,`SlotProvider` 被 `SlotSource#provide` 用于构造一个 `SlotCollection`:一个深拷贝 `ItemStack` 的流。存储在集合中的堆栈然后被传递到池的输出。由于这一切都在某个 `SlotSource#provide` 实现中完成,它可以引用任何东西(不仅仅是 `SlotProvider`),只要它可以将该数据转换为 `SlotCollection`。 ```java // 一个槽位来源,其“槽位”是物品标签中的元素。 public record TagSlotSource(TagKey tag) implements SlotSource { public static final MapCodec MAP_CODEC = TagKey.codec(Registries.ITEM) .fieldOf("tag").xmap(TagSlotSource::new, TagSlotSource::tag); @Override public SlotCollection provide(LootContext ctx) { // 获取标签的持有者集 Optional> holderSetOpt = ctx.getResolver() .lookup(Registries.ITEM).flatMap(getter -> getter.get(this.tag)); // 流式传输元素并映射到 SlotCollection return holderSetOpt.map(holderSet -> // `Item#getDefaultInstance` 返回一个新副本,因此可以使用。 // 如果 ItemStack 已经存在,则应对每个调用 `ItemStack#copy`。 (SlotCollection) () -> holderSet.stream().map(holder -> holder.value().getDefaultInstance()) ).orElse(SlotCollection.EMPTY); } @Override public MapCodec codec() { // 用于序列化槽位来源的编解码器 return MAP_CODEC; } } // 映射编解码器需要注册到槽位来源类型注册表 Registry.register( BuiltInRegistries.SLOT_SOURCE_TYPE Identifier.withNamespaceAndPath("examplemod", "tag"), TagSlotSource.MAP_CODEC ); ``` ```json5 // 一个示例战利品表 { // ... "pools": [ { "rolls": 1.0, "bonus_rolls": 0.0, "entries": [ { // 使用槽位来源战利品池 "type": "minecraft:slots", "slot_source": { // 我们的槽位来源 "type": "examplemod:tag", "tag": "minecraft:planks" } } ] } // ... ] } ``` - `net.minecraft.advancements.criterion.SlotsPredicate#matches` 现在接受 `SlotProvider` 而不是 `Entity` - `net.minecraft.core.registries.BuiltInRegistries#SLOT_SOURCE_TYPE`、`Registries#SLOT_SOURCE_TYPE` - 槽位来源类型注册表。 - `net.minecraft.world.Container` 现在扩展 `SlotProvider` - `getSlot` - 获取单个物品的访问。 - `net.minecraft.world.entity` - `Entity` 现在实现 `SlotProvider` - `SlotAccess` - `NULL` 已移除 - `forContainer` -> `forListElement`,不是一对一 - `SlotProvider` - 一个通过槽位提供对其内部存储的某些访问的对象。 - `net.minecraft.world.item.slot` - `CompositeSlotSource` - 多个槽位来源的组合。 - `ContentsSlotSource` - 获取槽位内容。 - `EmptySlotSource` - 一个空的槽位来源。 - `FilteredSlotSource` - 根据物品谓词过滤提供的槽位来源。 - `GroupSlotSource` - 将多个槽位来源组合成一个连接的集合。 - `LimitSlotSource` - 将提供的槽位来源限制为最大大小。 - `RangeSlotSource` - 获取所需的槽位范围。 - `SlotCollection` - 一个槽位的集合,用于获取物品副本。 - `SlotSource` - 给定战利品上下文,返回一个要提供的槽位集合。 - `SlotSources` - 原版提供的槽位来源。 - `TransformedSlotSource` - 转换提供的槽位来源。 - `net.minecraft.world.level.storage.loot.ContainerComponentManipulator#getSlots` - 获取堆栈上数据组件的槽位。 - `net.minecraft.world.level.storage.loot.entries` - `LootPoolEntries#SLOTS` - 一个使用来自源的槽位的池。 - `SlotLoot` - 一个从某个槽位来源获取其物品的池。 ### 僵尸鹦鹉螺变体 僵尸鹦鹉螺是变体数据包注册表对象的最新添加,接受熟悉的模型和纹理覆盖以及生成条件: ```json5 // 文件位于: // - `data/examplemod/zombie_nautilus_variant/example_zombie_nautilus.json` { // 指向 `assets/examplemod/textures/entity/nautilus/example_zombie_nautilus.png` 的纹理 "asset_id": "examplemod:entity/nautilus/example_zombie_nautilus", // 定义用于选择渲染僵尸鹦鹉螺变体的实体模型的 `ZombieNautilusVariant$ModelType` "model": "warm", "spawn_conditions": [ // 此变体生成的条件 { "priority": 0 } ] } ``` - `net.minecraft.core.component.DataComponents#ZOMBIE_NAUTILUS_VARIANT` - 僵尸鹦鹉螺的变体。 - `net.minecraft.core.registries.Registries#ZOMBIE_NAUTILUS_VARIANT` - 僵尸鹦鹉螺变体的注册表键。 - `net.minecraft.network.syncher.EntityDataSerializers#ZOMBIE_NAUTILUS_VARIANT` - 僵尸鹦鹉螺的变体。 - `net.minecraft.world.entity.animal.nautilus` - `ZombieNautilusVariant` - 僵尸鹦鹉螺的变体。 - `ZombieNautilusVariants` - 所有原版僵尸鹦鹉螺变体。 ### `OptionEnum` 移除 `OptionEnum` 已被移除,转而使用带有期望值和编解码器的 `OptionInstance$Enum` 构造函数。因此,大多数 `byId` 方法已被一些编解码器取代,并且可翻译条目现在存储为 `Component` 而不是翻译键字符串。 - `net.minecraft.client` - `AttackIndicatorStatus` 不再实现 `OptionEnum` - `byId` -> `LEGACY_CODEC`,不是一对一 - `getKey` -> `caption`,不是一对一 - `CloudStatus` 不再实现 `OptionEnum` - `getKey` -> `caption`,不是一对一 - `InactivityFpsLimit` 不再实现 `OptionEnum` - `getKey` -> `caption`,不是一对一 - `OptionInstance#forOptionEnum` 已移除 - `PrioritizeChunkUpdate` 不再实现 `OptionEnum` - `getKey` -> `caption`,不是一对一 - `byId` -> `LEGACY_CODEC`,不是一对一 - `net.minecraft.client.sounds.MusicManager$MusicFrequency` 不再实现 `OptionEnum` - `getKey` -> `caption`,不是一对一 - `net.minecraft.server.level.ParticleStatus` 不再实现 `OptionEnum` - `getKey` -> `caption`,不是一对一 - `byId` -> `LEGACY_CODEC`,不是一对一 - `net.minecraft.util.OptionEnum` 已移除 - `net.minecraft.world.entity.HumanoidArm` 不再实现 `OptionEnum` - `BY_ID` 现在是私有的 - `getKey` -> `caption`,不是一对一 - `net.minecraft.world.entity.player.ChatVisbility` 不再实现 `OptionEnum` - `byId` -> `LEGACY_CODEC`,不是一对一 - `getKey` -> `caption`,不是一对一 ### 特定逻辑变更 - `net.minecraft.client.renderer.entity.EntityRenderState#lightCoords` 现在默认为 0xF000F0。 - `net.minecraft.client.gui.screens.inventory.AbstractContainerScreen#keyPressed` 如果键未被屏幕处理,不再返回 `true`,而是返回 `false`。 - `net.minecraft.util.Mth#clampedLerp` 两个重载的参数顺序已重新排列。这些方法现在接受步长、原始值和下一个值;而不是原始值、下一个值和步长值。 ### 标签变更 - `minecraft:biome` - `plays_underwater_music` 已移除 - 被 `BackgroundMusic#underwaterMusic` 环境属性取代 - `has_closer_water_fog` 已移除 - 被 `EnvironmentAttributes#WATER_FOG_END_DISTANCE` 取代 - `increased_fire_burnout` 已移除 - 被 `EnvironmentAttributes#INCREASED_FIRE_BURNOUT` 取代 - `snow_golem_melts` 已移除 - 被 `EnvironmentAttributes#SNOW_GOLEM_MELTS` 取代 - `without_patrol_spawns` 已移除 - 被 `EnvironmentAttributes#CAN_PILLAGER_PATROL_SPAWN` 取代 - `spawns_coral_variant_zombie_nautilus` - `minecraft:block` - `can_glide_through` - `minecraft:entity_type` - `burn_in_daylight` - `can_float_while_ridden` - `can_wear_nautilus_armor` - `nautilus_hostiles` - `minecraft:item` - `camel_husk_food` - `zombie_horse_food` - `nautilus_bucket_food` - `nautilus_food` - `nautilus_taming_items` - `spears` - `enchantable/lunge` - `enchantable/sword` -> `enchantable/melee_weapon`、`enchantable/sweeping` - `minecraft:timeline` - `universal` - `in_overworld` - `in_nether` - `in_end` ### 新增列表 - `com.mojang.blaze3d.GraphicsWorkarounds#isAmd` - GPU 供应商是否为 AMD。 - `com.mojang.blaze3d.opengl` - `GlConst#GL_POINTS` - 定义点图元作为要渲染的类型。 - `GlTimerQuery` - 查询对象(通常是经过的时间)的 OpenGL 实现。 - `com.mojang.blaze3d.platform.InputConstants#MOUSE_BUTTON_*` - 鼠标点击的输入,用数字表示,因为它们可能有不同的预期用途。 - `com.mojang.blaze3d.systems` - `CommandEncoder#timerQueryBegin`、`timerQueryEnd` - 用于跟踪经过时间的处理程序。 - `GpuQuery` - 对任意对象的查询,例如经过的时间。 - `com.mojang.blaze3d.vertex` - `DefaultVertexFormat` - `POSITION_COLOR_LINE_WIDTH` - 一个指定位置、颜色和线宽的顶点格式。 - `POSITION_COLOR_NORMAL_LINE_WIDTH` - 一个指定位置、颜色、法线和线宽的顶点格式。 - `VertexFormat$Mode#POINTS` - 一个绘制点的顶点模式。 - `VertexFormatElement#LINE_WIDTH` - 一个接受一个表示宽度的浮点数的顶点元素。 - `com.mojang.math` - `OctahedralGroup` - `BLOCK_ROT_*` - 表示方块旋转的常量。 - `permutation` - 返回对称群。 - `Quadrant#fromXYZAngles` - 获取表示三个象限旋转的八面体群。 - `SymmetricGroup3#inverse` - 返回逆群。 - `net.minecraft` - `SharedConstants` - `MAX_CLOUD_DISTANCE` - 玩家可以渲染的最大云范围。 - `DEFAULT_RANDOM_TICK_SPEED` - 默认随机刻速度。 - `Util#localizedDateFormatter` - 返回给定样式的本地化 `DateTimeFormatter`。 - `net.minecraft.advancements.criterion` - `DataComponentMatchers$Builder#any` - 匹配组件的某些数据是否存在。 - `SpearMobsTrigger` - 一个触发器,检查玩家使用动能武器刺穿的实体数量。 - `net.minecraft.client` - `GuiMessage` - `splitLines` - 将组件以所需宽度拆分为行。 - `getTagIconLeft` - 获取内容的宽度,外加四个像素的填充。 - `KeyMapping$Category#DEBUG` - 调试键盘类别。 - `MusicToastDisplayState` - 一个枚举,表示音乐吐司应如何显示。 - `NarratorStatus#LEGACY_CODEC` - 用于反序列化枚举旁白状态的编解码器。 - `OptionInstance` - `$IntRangeBase` - `next` - 获取下一个值。 - `previous` - 获取上一个值。 - `$SliderableEnum` - 一个在枚举选项之间选择的滑块。 - `$SliderableValueSet` - `next` - 获取下一个值。 - `previous` - 获取上一个值。 - `Options` - `keyToggleGui` - 一个切换游戏内 GUI 的按键映射。 - `keyToggleSpectatorShaderEffects` - 一个切换与相机实体绑定的着色器效果的按键映射。 - `keyDebug*`、`debugKeys` - 调试渲染器的按键映射。 - `weatherRadius` - 区域中天气粒子渲染的半径。 - `cutoutLeaves` - 树叶是否应以切割或实体模式渲染。 - `vignette` - 是否应在屏幕上应用晕影。 - `improvedTransparency` - 是否使用透明度后处理器。 - `chunkSectionFadeInTime` - 区块首次渲染时淡入应花费的秒数。 - `maxAnisotropyBit` - 各向异性过滤级别的位值。 - `maxAnisotropyValue` - 各向异性过滤级别。 - `net.minecraft.client.animation.definitions.NautilusAnimation` - 鹦鹉螺的动画定义。 - `net.minecraft.client.data.models.ItemModelGenerators` - `generateSpear` - 生成矛物品模型。 - `generateItemWithTintedBaseLayer` - 生成一个基础层被染色的双层物品模型。 - `net.minecraft.client.data.models.model.ModelTemplates#SPEAR_IN_HAND` - 手持矛模型的模板。 - `net.minecraft.client.gui.components` - `AbstractButton#setOverrideRenderHighlightedSprite` - 覆盖是否使用聚焦启用/禁用精灵。 - `Checkbox#adjustWidth` - 使用消息、字体及其初始 X 位置设置小部件的宽度。 - `CycleButton` - `$Builder#withSprite` - 设置根据当前按钮状态获取精灵的供应商。 - `$DisplayState` - 按钮应如何显示。 - `$SpriteSupplier` - 根据当前按钮状态获取精灵位置。 - `EditBox#setInvertHighlightedTextColor` - 设置是否反转高亮文本颜色。 - `FocusableTextWidget` - `getPadding` - 返回文本填充。 - `updateWidth` - 更新文本可以占用的宽度。 - `updateHeight` - 更新文本可以占用的高度。 - `$Builder` - 构建组件。 - `MultiLineTextWidget#getTextX`、`getTextY` - 获取文本位置。 - `OptionsList` - `addHeader` - 添加一个标题条目。 - `resetOption` - 重置选项值。 - `$AbstractEntry` - 定义选择列表中的元素。 - `$HeaderEntry` - 一个表示部分标题的条目。 - `$OptionInstanceWidget` - 一个包含小部件和可选的选项实例的记录。 - `ResettableOptionWidget` - 一个可以将其值重置为默认值的小部件。 - `SelectableEntry` - 一个用于检查鼠标是否在特定区域的实用程序。 - `net.minecraft.client.gui.layouts.HeaderAndFooterLayout#MAGIC_PADDING` - 元素之间的常见填充。 - `net.minecraft.client.gui.screens.advancements` - `AdvancementTab#canScrollHorizontally`、`canScrollVertically` - 检查标签页数据是否可以在给定方向上滚动。 - `AdvancementTabType#getWidth`、`getHeight` - 获取标签页的宽度/高度。 - `net.minecraft.client.gui.screens.debug.DebugOptionsScreen#getOptionList` - 返回调试屏幕的选项列表。 - `net.minecraft.client.gui.screens.inventory` - `AbstractMountInventoryScreen` - 一个表示坐骑库存的屏幕。 - `EffectsInInventory` - `SPACING` - 效果之间的间距。 - `SPRITE_SQUARE_SIZE` - 效果图标的大小。 - `NautilusInventoryScreen` - 鹦鹉螺库存的屏幕。 - `net.minecraft.client.gui.screens.options` - `OptionsSubScreen#resetOption` - 将选项值重置为默认值。 - `VideoSettingsScreen#updateTransparencyButton` - 将透明度按钮设置为当前选项值。 - `net.minecraft.client.gui.screens.packs.TransferableSelectionList$PackEntry#ICON_SIZE` - 资源包图标的大小。 - `net.minecraft.client.gui.screens.recipebook.RecipeBookTabButton#select`、`unselect` - 处理标签页显示选择。 - `net.minecraft.client.input.InputQuirks#EDIT_SHORTCUT_KEY_LEFT`、`EDIT_SHORTCUT_KEY_RIGHT` -> `InputWithModifiers#hasControlDownWithQuirk`,不是一对一 - `net.minecraft.client.model.HumanoidModel$ArmPose` - `SPEAR` - 矛的第三人称手臂姿势。 - `animateUseItem` - 给定实体状态、使用时间、手臂和堆栈,修改 `PoseStack`。 - `affectsOffhandPose` - 手臂动画是否会影响副手姿势。 - `net.minecraft.client.model.animal.nautilus` - `NautilusArmorModel` - 鹦鹉螺的盔甲模型。 - `NautilusModel` - 鹦鹉螺的模型。 - `NautilusSaddleModel` - 鹦鹉螺的马鞍模型。 - `net.minecraft.client.model.effects.SpearAnimations` - 使用矛时执行的动画。 - `net.minecraft.client.model.geom` - `ModelLayers` - `*NAUTILUS*` - 鹦鹉螺的模型层。 - `UNDEAD_HORSE*_ARMOR` - 亡灵马的盔甲模型层。 - `PartName` - `INNER_MOUTH`、`LOWER_MOUTH` - 嘴的部件名称。 - `SHELL` - 壳的部件名称。 - `*_CORAL*` - 僵尸鹦鹉螺上珊瑚的部件名称。 - `net.minecraft.client.model.geom.builders.UVPair#pack`、`unpack*` - 处理将 UV 打包/解包为 `long`。 - `net.minecraft.client.model.monster.nautilus.ZombieNautilusCoralModel` - 僵尸鹦鹉螺温暖变体的模型。 - `net.minecraft.client.model.monster.skeleton.SkeletonModel#createSingleModelDualBodyLayer` - 创建一个焦尸层定义。 - `net.minecraft.client.multiplayer` - `ClientPacketListener#hasClientLoaded` - 客户端是否已加载。 - `MultiPlayerGameMode#piercingAttack` - 发起冲刺攻击。 - `net.minecraft.client.player.LocalPlayer#raycastHitResult` - 获取给定部分刻下相机实体的命中结果。 - `net.minecraft.client.renderer` - `DynamicUniforms` - `CHUNK_SECTION_UBO_SIZE` - 区块部分的统一缓冲区对象大小。 - `writeChunkSections` - 将可变参数的区块部分写入统一存储。 - `$ChunkSectionInfo` - 区块部分的动态统一变量。 - `GameRenderer` - `updateCamera` - 调用相机的设置函数。 - `getPanoramicScreenshotParameters` - 获取全景模式的截图参数。 - `PanoramicScreenshotParameters` - 全景模式的截图参数。 - `Sheets#CELESTIAL_SHEET` - 天体纹理的图集。 - `net.minecraft.client.renderer.blockentity.BlockEntityWithBoundingBoxRenderer#STRUCTURE_VOIDS_COLOR` - 结构的虚空颜色。 - `net.minecraft.client.renderer.chunk.SectionRenderDispatcher$RenderSection` - `getVisibility` - 返回区块当前的 alpha 值。 - `setFadeDuration` - 设置区块淡入所需的时间。 - `setWasPreviouslyEmpty`、`wasPreviouslyEmpty` - 处理该部分之前是否不存在。 - `net.minecraft.client.renderer.entity` - `CamelHuskRenderer` - 骆驼干尸的实体渲染器。 - `CamelRenderer#createCamelSaddleLayer` - 创建骆驼的马鞍层。 - `NautilusRenderer` - 鹦鹉螺的实体渲染器。 - `ParchedRenderer` - 焦尸的实体渲染器。 - `ZombieNautilusRenderer` - 僵尸鹦鹉螺的实体渲染器。 - `net.minecraft.client.renderer.entity.state` - `ArmedEntityRenderState` - `swingAnimationType` - 挥动手臂时播放的动画。 - `ticksUsingItem` - 物品已被使用的刻数。 - `getUseItemStackForArm` - 根据手臂返回持有的物品堆栈。 - `LivingEntityRenderState#ticksSinceKineticHitFeedback` - 自此实体被动能武器击中以来经过的刻数。 - `NautilusRenderState` - 鹦鹉螺的实体渲染状态。 - `UndeadRenderState` - 亡灵人形生物的实体渲染状态。 - `net.minecraft.client.renderer.item.ItemModelResolver#swapAnimationScale` - 获取堆栈交换动画的缩放。 - `net.minecraft.client.renderer.state.LevelRenderState#gameTime` - 当前游戏时间。 - `net.minecraft.client.resources.SplashManager` 组件字段 - 特殊消息的组件。 - `net.minecraft.client.resources.model` - `BlockModelRotation#IDENTITY` - 恒等旋转。 - `EquipmentClientInfo#NAUTILUS_*` - 鹦鹉螺的层。 - `net.minecraft.core.Vec3i` - `multiply` - 将每个分量乘以提供的标量。 - `toMutable` - 返回一个可变的 `Vector3i`。 - `net.minecraft.data.AtlasIds#CELESTIAL_SHEET` - 天体纹理的图集。 - `net.minecraft.data.recipes.RecipeProvider#waxedChiseled` - 打蜡的雕纹方块的配方。 - `net.minecraft.gametest.framework.GameTestHelper#getAbsoluteDirection` - 从测试相对方向返回绝对方向。 - `net.minecraft.nbt.NbtAccounter` - `defaultQuota` - 一个最大分配 2 MiB 的计数器。 - `uncompressedQuota` - 一个最大分配 100 MiB 的计数器。 - `net.minecraft.network.chat.MutableComponent#withoutShadow`、`Style#withoutShadow` - 从文本中移除阴影。 - `net.minecraft.network.protocol.game.ServerboundPlayerActionPacket$Action#STAB` - 玩家执行了刺击动作。 - `net.minecraft.network.syncher.EntityDataSerializers#HUMANOID_ARM` - 人形生物的主手。 - `net.minecraft.resources.Identifier#toShortString` - 返回位置的字符串。如果命名空间是 `minecraft`,则省略。 - `net.minecraft.server` - `MinecraftServer` - `getServerActivityMonitor` - 返回发送服务器活动通知的监视器。 - `getStopwatches` - 返回 id 到计时器的映射。 - `ServerScoreboard#storeToSaveDataIfDirty` - 如果脏则写入数据。 - `net.minecraft.server.commands.StopwatchCommand` - 一个启动或停止秒表的命令。 - `net.minecraft.server.dedicated.DedicatedServerProperties#managementServerAllowedOrigins` - 管理服务器的请求可以来自的来源。 - `net.minecraft.server.jsonrpc.OutgoingRpcMethods#SERVER_ACTIVITY_OCCURRED` - Minecraft 服务器发出的关于服务器活动发生的请求。 - `net.minecraft.server.jsonrpc.api.Schema` - `BOOL_OR_INT_SCHEMA` - 一个可以是布尔值或整数的字段的模式。 - `typedCodec` - 返回模式的编解码器。 - `info` - 返回模式的副本。 - `net.minecraft.server.level` - `ChunkMap#getChunkDataFixContextTag` - 返回区块数据的数据修复标签。 - `ServerLevel` - `getDayCount` - 获取经过的天数。 - `canSpreadFireAround` - 火是否可以在给定的方块位置周围蔓延。 - `net.minecraft.server.network` - `EventLoopGroupHolder` - 一个用于管理与某个端点(无论是本地还是基于套接字)通信的事件循环和通道的持有者。 - `ServerGamePacketListenerImpl#resetFlyingTicks` - 重置玩家已飞行的刻数。 - `net.minecraft.server.notifications` - `NotificationService#serverActivityOccurred` - 通知管理服务器活动已发生。 - `ServerActivityMonitor` - 发送服务器活动通知的监视器。 - `net.minecraft.util` - `ARGB` - `srgbToLinearChannel` - 将 sRGB 值转换为线性颜色空间。 - `linearToSrgbChannel` - 将线性值转换为 sRGB 颜色空间。 - `meanLinear` - 使用线性颜色空间计算四个值的平均值,然后将其转换回 sRGB。 - `addRgb` - 添加 RGB 通道,使用第一个值的 alpha。 - `subtractRgb` - 减去 RGB 通道,使用第一个值的 alpha。 - `multiplyAlpha` - 将 alpha 值乘入提供的 ARGB 值。 - `linearLerp` - 通过转换为线性颜色空间来线性插值颜色。 - `white`、`black` - 具有提供 alpha 的颜色。 - `alphaBlend` - 混合两种颜色及其 alpha 值。 - `vector4fFromARGB32` - 将 ARGB 值转换为四个浮点数。 - `Ease` - 一个充满缓动函数的实用工具。 - `ExtraCodecs` - `NON_NEGATIVE_LONG`、`POSITIVE_LONG` - 具有列出约束的长整数。 - `longRange` - 一个验证其是否在提供范围内的长整数编解码器。 - `STRING_RGB_COLOR`、`STRING_ARGB_COLOR` - 一个允许以十六进制字符串形式表示 (A)RGB 值的编解码器。 - `MAX_PROPERTY_NAME_LENGTH`、`MAX_PROPERTY_VALUE_LENGTH`、`MAX_PROPERTY_SIGNATURE_LENGTH`、`MAX_PROPERTIES` - 与序列化属性映射相关的常量。 - `Mth` - `cube` - 对数字进行立方。 - `chessboardDistance` - 计算两对坐标之间的绝对最大差值;返回较大的轴差。 - `SpecialDates` - 一个包含 Mojang 更改某些行为或渲染的日期的实用工具。 - `TriState` - `CODEC` - 三态布尔值的编解码器。 - `from` - 将布尔值转换为三态布尔值。 - `net.minecraft.util.profiling.jfr.JvmProfiler#onClientTick` - 在客户端Tick上运行,接受当前的 FPS。 - `net.minecraft.util.profiling.jfr.event.ClientFpsEvent` - 一个跟踪客户端 FPS 的事件。 - `net.minecraft.util.profiling.jfr.stats.FpsStat` - 一个包含客户端 FPS 的记录。 - `net.minecraft.world` - `LockCode#canUnlock` - 给定的玩家是否可以解锁此代码。 - `Stopwatch` - 一个包含创建时间和已用时间的记录。 - `Stopwatches` - 一个用于启动、管理和停止秒表的跟踪器。 - `net.minecraft.world.effect` - `MobEffects#BREATH_OF_THE_NAUTILUS` - 防止用户在水下失去空气。 - `MobEffectUtil#shouldEffectsRefillAirsupply` - 实体是否具有在液体中补充空气供应的效果。 - `net.minecraft.world.entity` - `Entity` - `getHeadLookAngle` - 计算头部旋转的视图向量。 - `updateDataBeforeSync` - 在同步到客户端之前更新实体中存储的数据。 - `computeSpeed` - 计算实体的最后已知速度和位置。 - `getKnownSpeed` - 获取实体的最后已知速度。 - `hasMovedHorizontallyRecently` - 如果最后已知速度的水平距离大于 0,更具体地说是误差范围。 - `EntityProcessor` - 加载实体时的后处理器。 - `EntityEvent#KINETIC_HIT` - 当实体被动能武器击中时触发的事件。 - `HumanoidArm#STREAM_CODEC` - 手臂枚举的网络编解码器。 - `LivingEntity` - `DEFAULT_KNOCKBACK` - 击中时应用于实体的默认击退。 - `itemSwapTicker` - 交换物品时花费的时间。 - `recentKineticEnemies` - 最近使用动能武器攻击的攻击者。 - `lungeForwardMaybe` - 应用冲刺效果。 - `causeExtraKnockback` - 对击退应用乘法力。 - `wasRecentlyStabbed`、`rememberStabbedEntity` - 处理被动能武器刺中的敌人。 - `stabAttack` - 处理生物被此实体刺中时的情况。 - `onAttack` - 处理此实体攻击另一个实体时的情况。 - `getTicksUsingItem` - 返回此物品已被使用的刻数。 - `getTicksSinceLastKineticHitFeedback` - 自上次被动能武器击中此实体以来经过的刻数。 - `shouldTravelInFluid` - 此实体是否应在给定的流体中移动。 - `travelInWater` - 移动实体,就像它们在水中一样。 - `Mob#sunProtectionSlot` - 保护实体免受阳光照射的装备槽位。 - `NeutralMob#level` - 返回实体所在的等级。 - `PlayerRideableJumping#getPlayerJumpPendingScale` - 返回玩家跳跃时应应用于实体的标量。 - `net.minecraft.world.entity.ai.attributes.Attributes#DEFAULT_ATTACK_SPEED` - 默认攻击速度。 - `net.minecraft.world.entity.ai.memory.MemoryModuleType` - `CHARGE_COOLDOWN_TICKS` - 冲刺攻击后的冷却刻数。 - `ATTACK_TARGET_COOLDOWN` - 攻击目标前的冷却刻数。 - `net.minecraft.world.entity.ai.sensing.TemptingSensor#forAnimal` - 一个传感器,特别处理动物实体,检查所需物品是否是食物。 - `net.minecraft.world.entity.animal.camel` - `Camel` - `getDashingSound`、`getDashReadySound` - 骆驼冲刺声音。 - `getStandUpSound`、`getSitDownSound` - 骆驼站/坐声音。 - `getSaddleSound` - 骆驼马鞍声音。 - `CamelHusk` - 骆驼干尸实体。 - `net.minecraft.world.entity.animal.equine.AbstractHorse#isMobControlled` - 生物是否可以控制这匹马。 - `net.minecraft.world.entity.animal.nautilus` - `AbstractNautilus` - 鹦鹉螺实体的核心。 - `Nautilus` - 鹦鹉螺实体。 - `NautilusAi` - 鹦鹉螺的大脑。 - `ZombieNautilus` - 僵尸鹦鹉螺实体。 - `ZombieNautilusAi` - 僵尸鹦鹉螺的大脑。 - `net.minecraft.world.entity.decoration.HangingEntity#hasLevelCollision` - 此实体是否在给定边界内与方块或边界碰撞。 - `net.minecraft.world.entity.monster.skeleton.Parched` - 焦尸实体。 - `net.minecraft.world.entity.monster.zombie.Husk$HuskGroupData` - 尸壳的群组数据。 - `net.minecraft.world.entity.player.Player` - `cannotAttackWithItem` - 检查玩家是否无法使用该物品攻击。 - `getItemSwapScale` - 返回用于物品交换动画的标量。 - `resetOnlyAttackStrengthTicker` - 重置攻击强度Tick器。 - `openNautilusInventory` - 打开交互的鹦鹉螺的库存。 - `applyPostImpulseGraceTime`、`isInPostImpulseGraceTime` - 处理脉冲之间的宽限期。 - `net.minecraft.world.food.FoodData#hasEnoughFood` - 当前食物水平是否大于 6 饥饿值(或三个完整的饥饿条)。 - `net.minecraft.world.inventory` - `AbstractMountInventoryMenu` - 坐骑的库存菜单。 - `NautilusInventoryMenu` - 鹦鹉螺的库存菜单。 - `net.minecraft.world.item` - `HoneycombItem#WAXED_RECIPES` - 打蜡方块到其配方类别和名称的映射。 - `Item$Properties` - `spear` - 添加矛组件。 - `nautilusArmor` - 添加鹦鹉螺盔甲组件。 - `ItemStack#matchesIgnoringComponents` - 堆栈是否匹配,忽略所有匹配谓词的组件。 - `ItemUseAnimation` - `TRIDENT` - 三叉戟使用动画。 - `hasCustomArmTransform` - 动画是否提供自定义的手臂变换。 - `net.minecraft.world.item.enchantment` - `Enchantment#doLunge` - 应用穿刺后攻击效果。 - `EnchantmentEffectComponents#POST_PIERCING_ATTACK` - 穿刺攻击后应用的效果。 - `EnchantmentHelper#doLungeEffects` - 在冲刺时应用效果。 - `LevelBasedValue$Exponent` - 应用给定基数和指数的指数。 - `net.minecraft.world.item.enchantment.effects` - `ApplyEntityImpulse` - 一个实体效果,在视角方向添加一个冲量。 - `ApplyExhaustion` - 一个实体效果,如果玩家正在使用附魔物品,则应用食物消耗。 - `ScaleExponentially` - 一个值效果,将值乘以某个数的指数次幂。 - `net.minecraft.world.level` - `Chunk#isValid` - 区块位置是否在允许的最大世界坐标内(在 3000 万方块半径内)。 - `CollisionGetter` - `noEntityCollision` - 实体在给定边界内是否不与另一个实体碰撞。 - `noBorderCollision` - 实体在给定边界内是否不与世界边界碰撞。 - `Level#isInValidBounds` - 方块位置是否不在允许的最大世界坐标外(Y 轴为建筑高度,XZ 轴为 3000 万方块半径)。 - `MoonPhase` - 一个表示月相的枚举。 - `net.minecraft.world.level.border.WorldBorder$MovingBorderExtent#getPreviousSize` - 获取边界的先前大小。 - `net.minecraft.world.level.chunk.storage` - `IOWorker#STORE_EMPTY` - 一个提供的 `null` 标签。 - `LegacyTagFixer` - 一个处理如何升级标签的接口,例如对于区块。 - `SimpleRegionStorage` - `isOldChunkAround` - 来自先前版本的区块是否仍然存在于此版本中。 - `injectDatafixingContext` - 当上下文不为 `null` 时,将其添加到给定的标签。 - `markChunkDone` - 将区块标记为已完成升级到当前版本。 - `chunkScanner` - 获取用于扫描区块的访问。 - `net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler#LAST_MONOLYTH_STRUCTURE_DATA_VERSION` - 返回包含故障巨石的最后数据版本。 - `net.minecraft.world.level.storage.loot.LootContextArg` - 用于查询的战利品上下文参数。 - `net.minecraft.world.level.storage.loot.functions.DiscardItem` - 一个丢弃战利品、返回空堆栈的战利品函数。 - `net.minecraft.world.phys.Vec3` - `offsetRandomXZ` - 在 XZ 方向上按随机量偏移点。 - `rotation` - 计算向量的旋转。 - `applyLocalCoordinatesToRotation` - 将相对于向量当前旋转的分量相加。 - `isFinite` - 返回向量的所有分量是否为有限值(不是 NaN 或无穷大)。 - `net.minecraft.world.scores` - `Scoreboard` - `packPlayerTeams` - 将玩家队伍打包成可序列化的格式。 - `packObjectives` - 将目标打包成可序列化的格式。 - `packDisplaySlots` - 将显示槽位打包成可序列化的格式。 - `ScoreboardSaveData` - `getData`、`setData` - 处理打包的记分板。 - `Packed$EMPTY` - 表示一个空的记分板。 - `net.minecraft.world.waypoints.Waypoint$Icon#copyFrom` - 从另一个图标复制图标颜色和样式。 ### 变更列表 - `com.mojang.blaze3d.platform.Lighting#updateLevel` 现在接受 `DimensionType$CardinalLightType` 而不是一个布尔值,表示等级是否不是下界 - `com.mojang.blaze3d.systems.GpuDevice#createTexture` 现在有一个接受提供的标签而不是原始字符串的重载 - `com.mojang.blaze3d.vertex.VertexConsumer` - `addVertex`、`addVertexWith2DPose` 现在接受其参数的接口、“只读”变体(例如,`Vector3f` -> `Vector3fc`) - `putBulkData` 不再接受最后的 `boolean` 来读取缓冲区数据以确定初始颜色 - `com.mojang.math` - `OctahedralGroup` - `fromXYAngles` -> `Quadrant#fromXYAngles` - `permute` -> `SymmetricGroup3#permuteAxis` - `SymmetricGroup3` - `permutation` -> `permute` - `permuteVector` -> `OctahedralGroup#rotate` - `Transformation` 现在接受其参数的接口、“只读”变体(例如,`Vector3f` -> `Vector3fc`) - 这也适用于参数获取器方法 - `net.minecraft` - `FileUtil#isValidStrictPathSegment` -> `containsAllowedCharactersOnly`,现在是私有的 - 被 `isValidPathSegment` 取代 - `Minecraft` - `disconnectWithProgressScreen` 现在接受一个 `boolean`,表示是否停止声音引擎 - `disconnect` 现在接受一个 `boolean`,表示是否停止声音引擎 - `SharedConstants` - `DEBUG_WATER` -> `DebugScreenEntries#VISUALIZE_WATER_LEVELS`,不是一对一 - `DEBUG_HEIGHTMAP` -> `DebugScreenEntries#VISUALIZE_HEIGHTMAP`,不是一对一 - `DEBUG_COLLISION` -> `DebugScreenEntries#VISUALIZE_COLLISION_BOXES`,不是一对一 - `DEBUG_SUPPORT_BLOCKS` -> `DebugScreenEntries#VISUALIZE_ENTITY_SUPPORTING_BLOCKS`,不是一对一 - `DEBUG_LIGHT` -> `DebugScreenEntries#VISUALIZE_BLOCK_LIGHT_LEVELS`、`VISUALIZE_SKY_LIGHT_LEVELS`;不是一对一 - `DEBUG_SKY_LIGHT_SECTIONS` -> `DebugScreenEntries#VISUALIZE_SKY_LIGHT_SECTIONS`,不是一对一 - `DEBUG_SOLID_FACE` -> `DebugScreenEntries#VISUALIZE_SOLID_FACES`,不是一对一 - `DEBUG_CHUNKS` -> `DebugScreenEntries#VISUALIZE_CHUNKS_ON_SERVER`,不是一对一 - `net.minecraft.advancements.criterion.EntityFlagsPredicate` 现在接受可选的布尔值,表示实体是否在水中或坠落飞行 - 关联的 `$Builder` 方法也已添加 - `net.minecraft.client` - `Camera` - `setup` 现在接受 `Level` 而不是 `BlockGetter` - `get*` 已被其记录替代(例如,`getEntity` -> `entity`) - `Vector3f` 返回值被 `Vector3fc` 取代 - `GraphicsStatus` -> `GraphicsPreset`,不是一对一 - `KeyMapping` 现在有一个接受排序顺序的重载 - `MouseHandler#lastClickTime` -> `lastClick`,现在是私有的,不是一对一 - `OptionInstance$OptionInstanceSliderButton` 现在实现 `ResettableOptionWidget` - `Options` - `graphicsMode` -> `graphicsPreset`、`applyGraphicsPreset` - `showNowPlayingToast` -> `musicToast`,不是一对一 - `net.minecraft.client.data.models` - `EquipmentAssetProvider#humanoidAndHorse` -> `humanoidAndMountArmor` - `ItemModelGenerators` - `getSpans` -> `getSideFaces`,不是一对一 - `$SpanFacing` -> `$SideDirection`,不是一对一 - `$Span` -> `$SideFace`,不是一对一 - `ItemModelOutput#accept` 现在有一个接受 `ClientItem$Properties` 的重载 - `net.minecraft.client.gui` - `Font#NO_SHADOW` -> `Style#NO_SHADOW` - `GuiGraphics` - `textHighlight` 现在接受一个 `boolean`,表示是否渲染背景矩形 - `submitOutline` -> `renderOutline` - `net.minecraft.client.gui.components` - `AbstractButton#handleCursor` -> `handleCursor`,现在是 protected - `AbstractSliderButton` - `HANDLE_WIDTH` 现在是 protected - `canChangeValue`、`setValue` 现在是 protected - `AbstractWidget#message` 现在是 protected - `CycleButton` 现在实现 `ResettableOptionWidget` - `builder` 现在有一个接受提供的默认值的重载 - `booleanBuilder` 现在接受一个布尔值来选择默认使用哪个组件 - `$Builder` 现在接受一个提供的默认值 - `displayOnlyValue(boolean)` -> `displayState`,不是一对一 - `FocusableTextWidget` 构造函数现在是包私有的,请使用 `builder` - `OptionsList` 现在将 `$AbstractEntry` 传递到泛型,而不是 `$Entry` - `addSmall` 现在有一个接受 `OptionInstance` 的重载 - `$Entry` 现在扩展 `$AbstractEntry` - `$OptionEntry` 类已移除 - `big` -> `$Entry#big` - `small` -> `$Entry#small` - `StringWidget#clipText` 现在是公开的静态方法,接受 `Font` - `net.minecraft.client.gui.components.debug` - `DebugScreenEntryList` - `toggleF3Visible` -> `toggleDebugOverlay` - `setF3Visible` -> `setOverlayVisible` - `isF3Visible` -> `isOverlayVisible` - `DebugScreenEntryStatus#IN_F3` -> `IN_OVERLAY` - `net.minecraft.client.gui.components.debugchart.AbstractDebugChart#COLOR_GREY` -> `CommonColors#TEXT_GRAY` - `net.minecraft.client.gui.components.toasts.ToastManager` - `createNowPlayingToast` -> `initializeMusicToast`,现在是私有的,不是一对一 - `removeNowPlayingToast` -> `setMusicToastDisplayState`,不是一对一 - `net.minecraft.client.gui.navigation.ScreenRectangle#transform*` 方法现在接受其参数的接口、“只读”变体(例如,`Vector3f` -> `Vector3fc`) - `net.minecraft.client.gui.render.state.*` 现在接受其 `pose` 的接口、“只读”变体(例如,`Vector3f` -> `Vector3fc`) - `GuiTextRenderState` 现在接受是否绘制每个字形周围的空白区域 - `net.minecraft.client.gui.screens` - `DeathScreen` 现在接受 `LocalPlayer` - `Screen` 现在有一个接受要使用的 `Minecraft` 实例和 `Font` 的重载 - `minecraft` 现在是 final - `font` 现在是 final - `init(Minecraft, int, int)` -> `init(int, int)` - `resize(Minecraft, int, int)` -> `init(int, int)` - `handleComponentClicked` -> `ChatScreen#handleComponentClicked`,现在是私有的 - `handleClickEvent` 已移至其关联的类,而不是一个超接口(例如,`BookViewScreen#handleClickEvent`) - `net.minecraft.client.gui.screens.advancements` - `AdvancementsScreen#renderWindow` 现在接受鼠标 XY `int` - `AdvancementTab#drawTab` 现在接受鼠标 XY `int` - `net.minecraft.client.gui.screens.debug.DebugOptionsScreen$OptionList` 现在是公开的 - `net.minecraft.client.gui.screens.inventory` - `AbstractCommandBlockEditScreen#populateAndSendPacket` 不再接受 `BaseCommandBlock` - `AbstractContainerScreen#renderSlots`、`renderSlot` 现在接受鼠标 XY `int` - `CreativeModeInventoryScreen#renderTabButton` 现在接受鼠标 XY `int` - `EffectsInInventory#renderEffects` -> `render` - `HorseInventoryScreen` 现在扩展 `AbstractMountInventoryScreen` - `MinecartCommandBlockEditScreen` 现在接受 `MinecartCommandBlock` 而不是 `BaseCommandBlock` - `net.minecraft.client.gui.screens.multiplayer.ServerSelectionList$OnlineServerEntry` 现在实现 `SelectableEntry` - `net.minecraft.client.gui.screens.packs.TransferableSelectionList$PackEntry` 现在实现 `SelectableEntry` - `net.minecraft.client.gui.screens.recipebook` - `RecipeBookComponent#initFilterButtonTextures` -> `getFilterButtonTextures`,不是一对一 - `RecipeBookTabButton` 现在实现 `ImageButton` 而不是 `StateSwitchingButton` - 构造函数现在接受 XY 位置以及 `Button$OnPress` 消费者 - `net.minecraft.client.gui.screens.worldselection.WorldSelectionList$WorldListEntry` 不再是静态的,现在实现 `SelectableEntry` - `net.minecraft.client.model` - `AnimationUtils` - `animateCrossbowCharge` 现在接受 `float` 而不是 `int` - `animateZombieArms` 现在接受 `UndeadRenderState` 而不是两个 `float` - `HumanoidModel` - `setupAttackAnimation` 不再接受 `float` - `getArm` 现在从 protected 变为 public - `net.minecraft.client.model.geom.ModelPart#getExtentsForGui` 现在接受 `Consumer` 而不是集合 - `net.minecraft.client.model.geom.builders.UVPair` 现在是一个记录 - `net.minecraft.client.multiplayer` - `MultiPlayerGameMode#isAlwaysFlying` -> `isSpectator` - `ServerStatusPinger#pingServer` 现在接受一个 `EventLoopGroupHolder` - `net.minecraft.client.renderer` - `CloudRenderer#render` 现在接受游戏时间 `long` - `DynamicUniforms#writeTransform`、`$Transform` 不再接受线宽 `float` - `GameRenderer#setPanoramicMode` -> `setPanoramicScreenshotParameters`,不是一对一 - `GlobalSettingsUniform#update` 现在接受 `Camera` 以及是否使用旋转网格超采样(RGSS) - `ItemBlockRenderTypes#setFancy` -> `setCutoutLeaves` - `ItemInHandRenderer` 不再接受 `ItemRenderer` - `LevelRenderer#isSectionCompiled` -> `isSectionCompiledAndVisible` - `RenderPipelines` - `LINE_STRIP` -> `LINES` 或 `LINES_TRANSLUCENT`,不是一对一 - `DEBUG_LINE_STRIP` -> `DEBUG_POINTS`,不是一对一 - `RenderType` - `LINE_STRIP`、`lineStrip` -> `RenderTypes#LINES`、`LINES_TRANSLUCENT`、`linesTranslucent`;不是一对一 - `debugLineStrip` -> `debugPoint`,不是一对一 - `SkyRenderer` 现在接受 `TextureManager` 和 `AtlasManager` - `extractRenderState` 现在接受 `Camera` 而不是相机位置 - `renderSunMoonAndStars` 现在接受 `MoonPhase` 而不是 `int` - `UniformValue` - `$IVec3Uniform` 现在接受 `Vector3ic` 而不是 `Vector3i` - `$Vec2Uniform` 现在接受 `Vector2fc` 而不是 `Vector2f` - `$Vec3Uniform` 现在接受 `Vector3fc` 而不是 `Vector3f` - `$Vec4Uniform` 现在接受 `Vector4fc` 而不是 `Vector4f` - `WeatherEffectRenderer#tickRainParticles` 现在接受一个 `int` 作为天气半径 - `WorldBorderRenderer#extract` 现在接受一个 `float` 作为部分刻 - `net.minecraft.client.renderer.blockentity` - `BannerRenderer#getExtents` 现在接受 `Consumer` 而不是集合 - `BedRenderer#getExtents` 现在接受 `Consumer` 而不是集合 - `BellRenderer#BELL_RESOURCE_LOCATION` -> `BELL_TEXTURE` - `DecoratedPotRenderer#getExtents` 现在接受 `Consumer` 而不是集合 - `EnchantTableRenderer#BOOK_LOCATION` -> `BOOK_TEXTURE` - `ShulkerBoxRenderer#getExtents` 现在接受 `Consumer` 而不是集合 - `TestInstanceRenderer` 不再接受 `BlockEntityRendererProvider$Context` - `net.minecraft.client.renderer.blockentity.state.BlockEntityWithBoundingBoxRenderState$InvisibleBlockType$STRUCUTRE_VOID` -> `STRUCTURE_VOID` - `net.minecraft.client.renderer.chunk.ChunkSectionLayer#textureView` -> `texture`,不是一对一 - `net.minecraft.client.renderer.entity.EntityRenderDispatcher` 不再接受 `ItemRenderer` - `net.minecraft.client.renderer.entity.layers` - `CarriedBLockLayer` 不再接受 `BlockRenderDispatcher` - `IronGolemFlowerLayer` 不再接受 `BlockRenderDispatcher` - `ItemInHandLayer#submitArmWithItem` 现在接受持有的 `ItemStack` - `net.minecraft.client.renderer.entity.state` - `ArmedEntityRenderState` - `*HandItem` -> `*HandItemState`、`*HandItemStack`;不是一对一 - `extractArmedRenderState` 现在接受部分刻 `float` - `HorseRenderState#bodyArmorItem` -> `EquineRenderState#bodyArmorItem` - `HumanoidRenderState` - `attackTime` -> `ArmedEntityRenderState#attackTime` - `ticksUsingItem` 现在是一个浮点数 - `IllagerRenderState` 现在扩展 `UndeadRenderState` - `ticksUsingItem` 现在是一个浮点数 - `ZombieRenderState` 现在扩展 `UndeadRenderState` - `ZombifiedPiglinRenderState` 现在扩展 `UndeadRenderState` - `net.minecraft.client.renderer.fog.FogRenderer#setupFog` 不再接受 `boolean` - `net.minecraft.client.renderer.fog.environment` - `AtmosphericFogEnvironment` 现在扩展 `FogEnvironment` 而不是 `AirBasedFogEnvironment` - `FogEnvironment#setupFog` 不再接受 `Entity` 和 `BlockPos`,而是接受 `Camera` - `net.minecraft.client.renderer.item.ClientItem$Properties` 现在接受一个浮点数,用于更改交换动画的缩放 - `net.minecraft.client.renderer.special.SpecialModelRenderer#getExtents` 现在接受 `Consumer` 而不是集合 - `net.minecraft.client.renderer.state.SkyRenderState#moonPhase` 现在是 `MoonPhase` 而不是 `int` - `net.minecraft.client.resources.SplashManager` - `prepare` 现在返回 `Component` 列表而不是字符串 - `apply` 现在接受 `Component` 列表而不是字符串 - `net.minecraft.client.resources.model.BlockModelRotation` 现在是一个类 - `by` -> `get`,不是一对一 - `net.minecraft.client.resources.sounds` - `RidingHappyGhastSoundInstance` -> `RidingEntitySoundInstance`,不是一对一 - `RidingMinecartSoundInstance` 现在扩展 `RidingEntitySoundInstance` 而不是 `AbstractTickableSoundInstance` - 构造函数现在接受 `SoundEvent`、最小和最大音量,以及放大器 - `SimpleSoundInstance#forMusic` 不再接受音量 - `net.minecraft.client.sounds` - `SoundEngine` 不再接受 `MusicManager` - `updateCategoryVolume` -> `refreshCategoryVolume` - `setVolume` -> `updateCategoryVolume`,不是一对一 - `SoundManager` 不再接受 `MusicManager` - `updateSourceVolume` -> `refreshCategoryVolume` - `setVolume` -> `updateCategoryVolume`,不是一对一 - `net.minecraft.gametest.framework.GameTestHelper` - `spawn` 现在有一个接受 `EntitySpawnReason` 或三个 `int` 作为位置的重载 - `assetTrue`、`assetFalse`、`assertValueEqual` 现在有一个接受 `String` 而不是 `Component` 的重载 - `assertEntityData` 现在有一个接受 `AABB` 边界框的重载 - `getRelativeBounds` 现在是公开的 - `assertEntityPosition` -> `assertEntityPresent`,不是一对一 - `net.minecraft.nbt` - `CompoundTag#remove` 现在返回被移除的标签 - `NbtUtils#getDataVersion` 现在有一个只接受 `CompoundTag` 的重载 - `net.minecraft.network` - `Connection` - `NETWORK_WORKER_GROUP` -> `EventLoopGroupHolder#NIO`,不是一对一 - `NETWORK_EPOLL_WORKER_GROUP` -> `EventLoopGroupHolder#EPOLL`,不是一对一 - `LOCAL_WORKER_GROUP` -> `EventLoopGroupHolder#LOCAL`,不是一对一 - `connectToServer`、`connect` 现在接受 `EventLoopGroupHolder` 而不是 `boolean` - `FriendlyByteBuf` - `writeVector3f` 现在接受 `Vector3fc` 而不是 `Vector3f` - `writeQuaternion` 现在接受 `Quaternionfc` 而不是 `Quaternionf` - `DEFAULT_NBT_QUOTA` -> `NbtAccounter#DEFAULT_NBT_QUOTA` - `net.minecraft.network.codec` - `ByteBufCodecs` - `VECTOR3F` 现在使用 `Vector3fc` 而不是 `Vector3f` - `QUATERNIONF` 现在使用 `Quaternionfc` 而不是 `Quaternionf` - `StreamCodec#composite` 现在有十个和十二个参数变体 - `net.minecraft.network.chat` - `ComponentUtils#mergeStyles` 现在有一个接受并返回 `Component` 的重载 - `MutableComponent` 现在是 final - `net.minecraft.network.protocol.game` - `ClientboundHorseScreenOpenPacket` -> `ClientboundMountScreenOpenPacket` - `ClientGamePacketListener#handleHorseScreenOpen` -> `handleMountScreenOpen` - `GamePacketTypes#CLIENTBOUND_HORSE_SCREEN_OPEN` -> `CLIENTBOUND_MOUNT_SCREEN_OPEN` - `net.minecraft.network.numbers` - `FixedFormat` 现在是一个记录 - `StyledFormat` 现在是一个记录 - `net.minecraft.network.syncher.EntityDataSerializers` - `VECTOR3` 现在使用 `Vector3fc` 而不是 `Vector3f` - `QUATERNION` 现在使用 `Quaternionfc` 而不是 `Quaternionf` - `net.minecraft.server` - `MinecraftServer` - `isAllowedToEnterPortal` -> `ServerLevel#isAllowedToEnterPortal` - `isSpawningMonsters` -> `ServerLevel#isSpawningMonsters` - `isPvpAllowed` -> `ServerLevel#isPvpAllowed` - `isCommandBlockEnabled` -> `ServerLevel#isCommandBlockEnabled` - `isSpawnerBlockEnabled` -> `ServerLevel#isSpawnerBlockEnabled` - `getGameRules` -> `ServerLevel#getGameRules` - `isEpollEnabled` -> `useNativeTransport` - `ServerScoreboard` 不再实现其自己的保存数据类型,而是使用打包的 `ScoreboardSaveData` - `TYPE` -> `ScoreboardSavedData#TYPE` - `net.minecraft.server.jsonrpc` - `IncomingRpcMethod` 现在接受两个泛型,分别用于请求的参数和结果响应 - `$Builder` 现在有无参数和参数函数的构造函数,取代了 `$Factory` - `response`、`param` 现在接受它们的 `Schema` - `OutgoingRpcMethod$Factory` 现在接受泛型参数和结果 - `net.minecraft.server.jsonrpc.api` - `MethodInfo`、`$Named` 现在接受两个泛型,分别用于请求的参数和结果响应 - `PARAMS_CODEC` -> `paramsTypedCodec`,现在是私有的,不是一对一 - `MAP_CODEC` -> `typedCodec`,现在是包私有的,不是一对一 - `ParamInfo` 现在接受一个参数的泛型 - `CODEC` -> `typedCodec`,不是一对一 - `ResultInfo` 现在接受一个结果响应的泛型 - `CODEC` -> `typedCodec`,不是一对一 - `Schema` 现在接受一个其表示类型的泛型 - 构造函数现在接受一个类型列表而不是一个可选项、一个非可选的属性映射、非可选的枚举值,以及用于序列化类型的编解码器 - `ofTypes` 现在有一个接受类型列表的重载 - `SchemaComponent` 现在接受一个其表示类型的泛型 - `net.minecraft.server.jsonrpc.security.AuthenticationHandler` 现在实现 `ChannelDuplexHandler` 而不是 `ChannelInboundHandlerAdapter` - 构造函数现在接受一个允许的来源的字符串集合 - `$SecurityCheckResult#allowed` 现在有一个重载,指定令牌是否通过 websocket 协议发送 - `net.minecraft.server.level` - `ChunkMap` 现在扩展 `SimpleRegionStorage` 而不是 `ChunkStorage` - `ServerLevel#drop` 不再返回 `boolean` - `net.minecraft.server.network.ServerConnectionListener` - `SERVER_EVENT_GROUP` -> `EventLoopGroupHolder#NIO`,不是一对一 - `SERVER_EPOLL_EVENT_GROUP` -> `EventLoopGroupHolder#EPOLL`,不是一对一 - `net.minecraft.stats.ServerStatsCounter` 现在接受 `Path` 而不是 `File` - `parseLocal` -> `parse`,不是一对一 - `toJson` 现在返回 `JsonElement` 而不是 `String` - `net.minecraft.util` - `ARGB#lerp` -> `srgbLerp` - `ExtraCodecs` 现在使用其泛型的接口、“只读”变体(例如,`Vector3f` -> `Vector3fc`) - `Mth` - `easeInOutSine` -> `Ease#inOutSine` - `sin`、`cos` 现在接受 `double` 而不是 `float` - `absMax` 现在有使用 `int` 或 `float` 的重载 - `TriState` 现在实现 `StringRepresentable` - `net.minecraft.util.profiling.jfr.Percentiles#evaluate` 现在有一个接受 `int[]` 的重载 - `net.minecraft.util.profiling.jfr.parse.JfrStatsResult` 现在接受一个 FPS 统计信息 - `tickTimes` -> `serverTickTimes` - `net.minecraft.util.profiling.jfr.stats.TimedStatSummary#summary` 现在返回 `TimeStatSummary` 的可选值 - `net.minecraft.util.worldupdate.WorldUpgrader` - `$AbstractUpgrader` 不再接受泛型 - `createStorage` 现在返回 `SimpleRegionStorage` 而不是泛型 - `tryProcessOnePosition` 现在接受 `SimpleRegionStorage` 而不是泛型 - `$DimensionToUpgrade` 不再接受泛型,而是使用 `SimpleRegionStorage` - `net.minecraft.world.RandomSequences` 不再接受世界种子 - `codec` -> `CODEC` - `get`、`reset` 现在接受世界种子 - `net.minecraft.world.entity` - `Avatar#DATA_PLAYER_MAIN_HAND` 现在使用 `HumanoidArm` 泛型而不是字节 - `Entity#hasImpulse` -> `needsSync` - `EntityType#loadEntityRecursive` 现在接受 `EntityProcessor` 而不是 `Function` - `LivingEntity#invulnerableDuration` -> `INVULNERABLE_DURATION` - `Mob#playAttackSound` -> `LivingEntity#playAttackSound` - `NeutralMob` - `TAG_ANGER_TIME` -> `TAG_ANGER_END_TIME`,不是一对一 - `getRemainingPersistentAngerTime` -> `getPersistentAngerEndTime`,不是一对一 - `setRemainingPersistentAngerTime` -> `setTimeToRemainAngry`、`setPersistentAngerEndTime`;第二个不是一对一 - `getPersistentAngerTarget`、`setPersistentAngerTarget` 现在处理 `EntityReference` - `net.minecraft.world.entity.ai.sensing.SensorType#*_TEMPTATIONS` -> `FOOD_TEMPTATIONS`,不是一对一 - `net.minecraft.world.entity.ai.util` - `GoalUtils` - `mobRestricted` 现在接受 `double` 而不是 `int` - `isRestricted` 现在有一个接受 `Vec3` 的重载 - `LandRandomPos` - `getPosAway` 现在有一个接受额外 `double` 作为起始/结束弧度的重载 - `generateRandomPosTowardDirection` 现在接受 `double` 而不是 `int` - `RandomPos` - `generateRandomDirectionWithinRadians` 现在接受 `double` 作为起始/结束弧度 - `generateRandomPosTowardDirection` 现在接受 `double` 而不是 `int` - `net.minecraft.world.entity.animal.equine.AbstractHorse#getInventorySize` -> `AbstractMountInventoryMenu#getInventorySize` - `net.minecraft.world.entity.monster.Monster#checkMonsterSpawnRules` 现在将其类型泛型扩展为 `Mob` 而不是 `Monster` - `net.minecraft.world.entity.monster.skeleton.Bogged#*_ATTACK_INTERVAL` -> `AbstractSkeleton#INCREASED_*_ATTACK_INTERVAL` - `net.minecraft.world.entity.monster.zombie` - `Husk#checkHuskSpawnRules` -> `Monster#checkSurfaceMonsterSpawnRules`,不是一对一 - `Zombie` - `doUnderWaterConversion` 现在接受 `ServerLevel` - `convertToZombieType` 现在接受 `ServerLevel` - `net.minecraft.world.entity.npc.villager` - `AbstractVillager` - `updateTrades` 现在接受 `ServerLevel` - `addOffersFromItemListings` 现在接受 `ServerLevel` - `Villager#shouldRestock` 现在接受 `ServerLevel` - `VillagerTrades$ItemListing#getOffer` 现在接受 `ServerLevel` - `net.minecraft.world.entity.player.Player` - `openMinecartCommandBlock` 现在接受 `MinecartCommandBlock` 而不是 `BaseCommandBlock` - `sweepAttack` -> `doSweepAttack`,现在是私有的,不是一对一 - `respawn` -> `LocalPlayer#respawn` - `CLIENT_LOADED_TIMEOUT_TIME` -> `ServerGamePacketListenerImpl#CLIENT_LOADED_TIMEOUT_TIME` - `clientLoadedTimeoutTimer`、`tickClientLoadTimeout` -> `ServerGamePacketListenerImpl#tickClientLoadTimeout` - `hasClientLoaded` -> `ServerGamePacketListenerImpl#hasClientLoaded` - `setClientLoaded` -> `ServerGamePacketListenerImpl#markClientLoaded`、`markClientUnloadedAfterDeath`、`restartClientLoadTimerAfterRespawn`;不是一对一 - `net.minecraft.world.entity.projectile.Projectile` 构造函数现在是 `protected` 而不是包私有的 - `net.minecraft.world.entity.vehicle.VehicleEntity#shouldSourceDestroy` 现在是 `protected` 而不是包私有的 - `net.minecraft.world.entity.vehicle.minecart` - `AbstractMinecart` 现在接受 `ServerLevel` - `MinecartCommandBlock$MinecartCommandBase` 现在是包私有的 - `net.minecraft.world.inventory.HorseInventoryMenu` 现在扩展 `AbstractMountInventoryMenu` - `net.minecraft.world.item.component.ItemAttributeModifiers#compute` 现在接受 `Attribute` 持有者 - `net.minecraft.world.item.enchantment.effects.PlaySoundEffect` 现在接受一个声音事件列表而不是单个 - `net.minecraft.world.level` - `BaseCommandBlock` - `performCommand` 现在接受 `ServerLevel` 而不是 `Level` - `onUpdated` 现在接受 `ServerLevel` - `createCommandSourceStack` 现在接受 `ServerLevel` - `$CloseableCommandBlockSource` 现在接受 `ServerLevel`,其构造函数是 protected - `CollisionGetter#noBlockCollision` 现在有一个接受额外 `boolean` 的重载,表示是否检查液体碰撞。 - `Level#getGameTime` -> `LevelAccessor#getGameTime` - `LevelAccessor#getCurrentDifficultyAt` -> `ServerLevelAccessor#getCurrentDifficultyAt` - `LevelTimeAccess#getMoonPhase` 现在返回 `MoonPhase` 而不是 `int` - `net.minecraft.world.level.biome` - `AmbientAdditionsSettings` 现在是一个记录 - `AmbientMoodSettings` 现在是一个记录 - `AmbientParticleSettings` 现在是一个记录 - `net.minecraft.world.level.block.entity.BaseContainerBlockEntity#canUnlock` -> `sendChestLockedNotifications`,不是一对一 - `net.minecraft.world.level.border` - `BorderChangeListener#onLerpSize` 现在接受一个额外的 `long` 作为游戏时间 - `WorldBorder` 现在可以接受 `WorldBorder$Settings` - `getMin*`、`getMax*` 现在有一个接受部分刻 `float` 的重载 - `lerpSizeBetween` 现在接受一个额外的 `long` 作为游戏时间 - `applySettings` -> `applyInitialSettings`,不是一对一 - 原始行为可以通过将设置传递给构造函数来复制 - `$BorderExtent#getMin*`、`getMax*` 现在接受部分刻 `float` - `net.minecraft.world.level.chunk.storage` - `RecreatingSimpleRegionStorage` 现在接受一个提供的 `LegacyTagFixer` - `SimpleRegionStorage` 现在接受一个提供的 `LegacyTagFixer` - `write` 现在有一个接受提供的 `CompoundTag` 的重载 - `upgradeChunkTag` 现在有一个接受可为空的标签上下文的重载 - `net.minecraft.world.level.dimension.DimensionType` - `MOON_PHASES` 现在是一个 `MoonPhase` 数组并且是私有的 - `moonPhase` 现在返回 `MoonPhase` 而不是 `int` - `net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler` 现在实现 `LegacyTagFixer` - 构造函数现在接受 `DataFixer` - `removeIndex` -> `LegacyTagFixer#markChunkDone` - `updateFromLegacy` 现在是私有的 - `getLegacyStructureHandler` 现在接受 `DataFixer`、一个提供的 `DimensionDataStorage`,并返回一个提供的 `LegacyTagFixer` - `net.minecraft.world.level.levelgen.structure.structures.NetherFortressPieces$StartPiece` 字段现在是包私有的 - `net.minecraft.world.level.saveddata.SavedDataType` 不再接受 `SavedData$Context`,移除了函数参数构造函数 - `net.minecraft.world.level.storage` - `DimensionDataStorage` 不再接受 `SavedData$Context` - `FileNameDateFormatter#create` -> `FORMATTER` - `LevelStorageSource` - `UNCOMPRESSED_NBT_QUOTA` -> `NbtAccounter#UNCOMPRESSED_NBT_QUOTA`,现在是 `public` - `$LevelDirectory#corruptedDataFile`、`rawDataFile` 现在接受 `ZonedDateTime` 而不是 `LocalDateTime` - `net.minecraft.world.level.storage.loot.LootContext` - `$BlockEntityTarget` 现在实现 `LootContextArg$SimpleGetter` - `getParam` -> `contextParam` - `$EntityTarget` 现在实现 `LootContextArg$SimpleGetter` - `getParam` -> `contextParam` - `$ItemStackTarget` 现在实现 `LootContextArg$SimpleGetter` - `getParam` -> `contextParam` - `net.minecraft.world.level.storage.loot.functions` - `CopyComponentsFunction` - `$*Source` -> `$DirectSource`,不是一对一 - `$Source` -> `LootContextArg$Getter`,不是一对一 - `CopyNameFunction#copyName` 现在接受 `LootContextArg` 而不是 `$Source` - `$Source` -> `LootContextArg`,不是一对一 - `FilteredFunction` 现在接受一个可选的通过和失败的 `LootItemFunction` 而不是仅仅一个修改器 - 该函数现在可以通过 `$Builder` 通过 `filtered` 构建 - `net.minecraft.world.phys.Vec3` 现在接受 `Vector3fc` 而不是 `Vector3f` - `net.minecraft.world.phys.shapes.Shapes#rotateHorizontal`、`rotateAll`、`rotateAttachFace` 现在有接受 `OctahedralGroup` 的重载 - `net.minecraft.world.scores` - `Score` 现在有一个用于 `$Packed` 值的公共构造函数 - `MAP_CODEC` -> `Score$Packed` 及其 `$Packed#MAP_CODEC` - `Scoreboard$PackedScore#score` 现在接受 `Score$Packed` 而不是 `Score` - `ScoreboardSavedData` 现在接受 `ScoreboardSaveData$Packed` 而不是 `Scoreboard` - `FILE_ID` 合并到类型中 - `loadFrom` -> `ServerScoreboard#load` - `pack` -> `ServerScoreboard#store`,现在是私有的,不是一对一 ### 移除列表 - `com.mojang.blaze3d.vertex.VertexFormat$Mode#LINE_STRIP` - `net.minecraft.Util#lastOf` - `net.minecraft.client` - `Minecraft#useFancyGraphics` - `GuiMessage#icon` - `StringSplitter` - `formattedIndexByWidth`、`componentStyleAtWidth` - `splitLines(FormattedText, int, Style, FormattedText)` - `net.minecraft.client.gui.Font#wordWrapHeight(String, int)` - `net.minecraft.client.gui.components` - `CycleButton` - `onOffBuilder()` - `$Builder#withInitialValue` - `StateSwitchingButton` - `net.minecraft.client.gui.screens.inventory` - `EffectsInInventory#renderTooltip` - `InventoryScreen#renderEntityInInventory` - `net.minecraft.client.gui.screens.packs.PackSelectionScreen#clearSelected` - `net.minecraft.client.player.LocalPlayer#USING_ITEM_SPEED_FACTOR` - `net.minecraft.client.renderer` - `ItemModelGenerator#createOrExpandSpan` - `GpuWarnlistManager#dismissWarningAndSkipFabulous`、`isSkippingFabulous` - `RenderPipelines` - `DEBUG_STRUCTURE_QUADS`、`DEBUG_SECTION_QUADS` - `SkyRenderer#initTextures` - `net.minecraft.client.renderer.fog.environment` - `AirBasedFogEnvironment` - `DimensionOrBossFogEnvironment` - `FogEnvironment#onNotApplicable` - `net.minecraft.client.resources.model.BlockModelRotation#actualRotation` - `net.minecraft.gametest.framework.GameTestHelper#setNight`、`setDayTime` - `net.minecraft.network.FriendlyByteBuf#readDate`、`writeDate` - `net.minecraft.server` - `MinecraftServer#hasGui` - `ServerScoreboard#createData`、`addDirtyListener` - `net.minecraft.server.jsonrpc.IncomingRpcMethod$Factory` - `net.minecraft.server.jsonrpc.methods.IllegalMethodDefinitionException` - `net.minecraft.server.jsonrpc.security.AuthenticationHandler#AUTH_HEADER` - `net.minecraft.util` - `DebugBuffer` - `LazyLoadedValue` - `net.minecraft.util.thread.NamedThreadFactory` - `net.minecraft.world.entity.Mob#isSunBurnTick` - `net.minecraft.world.entity.animal.armadillo.ArmadilloAi#getTemptations` - `net.minecraft.world.entity.animal.axolotl.AxolotlAi#getTemptations` - `net.minecraft.world.entity.animal.camel.CamelAi#getTemptations` - `net.minecraft.world.entity.animal.equine.ZombieHorse#checkZombieHorseSpawnRules` - 请改用 `Monster#checkMonsterSpawnRules` - `net.minecraft.world.entity.animal.goat.GoatAi#getTemptations` - `net.minecraft.world.entity.animal.sniffer.SnifferAi#getTemptations` - `net.minecraft.world.entity.player.Player#playNotifySound` - `net.minecraft.world.entity.raid.Raid#TICKS_PER_DAY` - `net.minecraft.world.level` - `BaseCommandBlock` - `getLevel` - `getUsedBy`、`getPosition` - `Level#TICKS_PER_DAY` - `net.minecraft.world.level.border.WorldBorder$Settings#toWorldBorder` - 请改用 `WorldBorder` 构造函数 - `net.minecraft.world.level.chunk.storage` - `ChunkStorage` - `RecreatingChunkStorage` - `net.minecraft.world.level.saveddata.SavedData$Context` - `net.minecraft.world.phys.Vec3#fromRGB24`